IFUSimComplete.mesa
Last Edited by Curry September 10, 1986 8:15:41 pm PDT
DIRECTORY Convert, Core, CoreCreate, CoreIO, CoreOps, CoreClasses, CoreName, CoreProperties, HashTable, IFUSim, IO, Rope, Rosemary;
IFUSimComplete: CEDAR PROGRAM
IMPORTS Convert, CoreClasses, CoreCreate, CoreName, CoreIO, CoreOps, CoreProperties, HashTable, IO, Rope, Rosemary
EXPORTS IFUSim =
BEGIN
CellType: TYPE = Core.CellType;
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, adj: BOOL];
WR:  TYPE = REF ← NIL;
FormalIFU: PUBLIC PROC RETURNS[ifu: CellType] = {
formalName: ROPE  ← "FormalIFU";
subCell:  CellType ← CoreOps.Recast[CoreIO.RestoreCellType["IFUComplete"]];
rec:   CoreClasses.RecordCellType;
publics:  Wires  ← NIL;
actual:  Wire  ← CoreOps.CreateWires[size: subCell.public.size];
nameFields: Table  ← HashTable.Create[];
newPubs:  Table  ← HashTable.Create[];
Register: PROC[old, new: ROPE, size: INT ← 0, index: INT ← -1, adj: BOOLTRUE] = {
f:  Field;
wire: Wire;
new ← CoreName.RopeNm[new];
wire ← NARROW[HashTable.Fetch[newPubs, new].value];
IF wire=NIL THEN {
wire ← CoreCreate.Seq[name: new, size: size];
[] ← HashTable.Store[newPubs, new, wire]};
IF wire.size#size THEN ERROR;
f ← NEW[FieldRec ← [
root: CoreName.RopeNm[old],
wire: (IF index#-1 THEN wire[index] ELSE wire),
adj: adj] ];
publics ← CONS[wire, publics];
[] ← HashTable.Store[nameFields, f.root, f]};
[] ← MarkWeakTransistors[subCell, "VBB"];
Register[ "Pad-IPAddr",      "IPData",     32  ];
Register[ "Pad-NewFetchBAA",    "IPCmdA",     8, 7 ];
Register[ "Pad-IPFaultingB",     "IPFaultB",     4, 0 ];
Register[ "Pad-IPRejectB",      "IPRejectB"      ];
Register[ "Pad-DPCmnd3ABB",    "DPCmdA",     8  ];
Register[ "Pad-DPFaultB",      "DPFaultB",      4  ];
Register[ "Pad-DPRejectB",     "DPRejectB"      ];
Register[ "Pad-EUAluOp2ABB",    "EUAluOp2AB",    4  ];
Register[ "Pad-EUCondSel2ABB",    "EUCondSel2AB",   4  ];
Register[ "Pad-EURdFromPBus3ABB",  "EURdFromPBus3AB"   ];
Register[ "Pad-EUWriteToPBus3ABB",  "EUWriteToPBus3AB"   ];
Register[ "Pad-EUCondition2B",    "EUCondition2B"    ];
Register[ "Pad-XBus",       "KBus",     32  ];
Register[ "Pad-ResetAB",      "ResetAB"      ];
Register[ "Pad-RescheduleAB",    "RescheduleAB"     ];
Register[ "PhA",        "PhA"        ];
Register[ "PhB",        "PhB"        ];
Register[ "NotPhA",       "NotPhA"       ];
Register[ "NotPhB",       "NotPhB"       ];
Register[ "NotPreChg",       "NotPhA"       ];
Register[ "DShA",        "DShA"       ];
Register[ "DShB",        "DShB"       ];
Register[ "DShRd",        "DShRd"       ];
Register[ "DShWt",        "DShWt"       ];
Register[ "Pad-DShIn",       "DShIn"       ];
Register[ "Pad-DShOut",      "DShOut"       ];
Register[ "VDD",        "Vdd"        ];
Register[ "GND",        "Gnd"        ];
Register[ "PadVDD",       "PadVdd"       ];
Register[ "PadGND",       "PadGnd"       ];
Register[ "VBB",        "Vdd"        ];
Register[ "FireControlV",      "Vdd"        ];
FOR index: INT IN [0..actual.size) DO
f:    Field;
name:   ROPE ← CoreName.WireNm[subCell.public[index]].n;
sigRec:  CoreName.SigRec ← NameSig[name];
idx:   INT ← sigRec.idx;
IF subCell.public[index].size#0 THEN ERROR;
sigRec.idx ← -1;
name   ← CoreName.SigName[sigRec];
f ← NARROW[HashTable.Fetch[nameFields, name].value];
IF f=NIL THEN ERROR;
actual[index] ← IF f.wire.size=0
THEN f.wire
ELSEIF f.adj
THEN f.wire[ Adj[ idx ] ]
ELSE f.wire[  idx ];
ENDLOOP;
rec  ← NEW [CoreClasses.RecordCellTypeRec[1]];
ifu  ← NEW [Core.CellTypeRec ← [
class:  CoreClasses.recordCellClass,
public: CoreOps.CreateWire[publics],
data:  rec ]];
rec.internal ← CoreOps.CreateWire[publics];
rec[0]   ← NEW [CoreClasses.CellInstanceRec ← [actual: actual, type: subCell]];
[ ] ← CoreOps.SetCellTypeName[ifu, formalName]};
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]};
transistorGateCount: PUBLIC ATOM ← CoreIO.RegisterProperty[
CoreProperties.RegisterProperty[
$TransistorGateCount,
CoreProperties.Props[
[CoreProperties.propCompare, CoreProperties.PropIntCompare],
[CoreProperties.propCopy,  NEW[CoreProperties.PropCopyProc ← CopyINT ]],
[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] ] ]};
CopyINT: CoreProperties.PropCopyProc ={RETURN[NEW[INTNARROW[value, REF INT]^]]};
PrintTGC: CoreProperties.PropPrintProc =
{to.PutF[" Transistor Gate Count: %g", IO.int[NARROW[val, REF INT]^]]};
MarkWeakTransistors: PROC [cell: CellType, wr: WR] 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    => ERROR;
IF gate=NIL THEN ERROR;
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;
IF data.instances[child].type.class = CoreClasses.transistorCellClass
THEN {
IF data.instances[child].type.public[0] # wires.first THEN ERROR;
[ ] ← Rosemary.SetTransistorInstanceSize[data.instances[child], driveWeak];
cnt ← 1}
ELSE cnt ← MarkWeakTransistors[ data.instances[child].type, wires.first ];
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 ← MarkWeakTransistors[ 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: 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};
END.