IPChipRoseImpl:
CEDAR
PROGRAM
IMPORTS IO, FS, SymTab, Atom, Rope, TerminalIO, CD, CDIO, CDDirectory, ReadConnection, IP, IPBasicOps, IPToolBox, IPTypeDict
EXPORTS IPChipRose = BEGIN OPEN RC: ReadConnection, BO: IPBasicOps, TD: IPTypeDict, TB: IPToolBox, IPChipRose;
NameConflict: PUBLIC ERROR [name: Rope.ROPE, in: Which] = CODE;
UnDeclared: PUBLIC ERROR[name: Rope.ROPE, in: Which] = CODE;
CreateFrom:
PUBLIC
PROC[roseFile, chipFile, typFile, initFile: Rope.
ROPE ←
NIL, chipBeforeTyp, debug:
BOOL]
RETURNS [Ref] ={
r: Ref ← NEW[Rep ← [nets: SymTab.Create[], ports: SymTab.Create[], instances: SymTab.Create[], types: SymTab.Create[]]];
cdDesign: CD.Design ← IF chipFile = NIL THEN NIL ELSE CDIO.ReadDesign[chipFile];
ipTypDict:
TD.Ref ←
IF typFile =
NIL
THEN
NIL
ELSE
TD.Create[typFile];
-- NB: This can only be used once (see FromIPType)
-- otherwise there may be confusions in the
-- TD.TypeEntryRep.shape and TD.TypeEntryRep.pins
--These are procedures to build up entries in symTabs of r--
--(1) This is simply to get the name of the assembly, other headers are ignored
headerProc: ReadConnection.EnumHeaderProc = {
IF Rope.Equal[key, "CellTypeName"] THEN r.cellTypeName ← val1}; --headerProc--
--(2)
portsProc: ReadConnection.EnumPortsProc = {
WHILE portList #
NIL
DO
IF ~ r.ports.Insert[portList.first.portName, NEW[PortRec ← [portList.first.ecName, NIL, portList.first.portDir]]] THEN ERROR IP.Error[doubleRegistration, portList.first.portName];
portList ← portList.rest
ENDLOOP;
};--portsProc--
--(3)
netProc: ReadConnection.EnumNetsProc= {
IF ~ r.nets.Insert[netName,
NEW[NetRec ← [generation]]]
THEN ERROR IP.Error[doubleRegistration, netName];
};--netProc--
--(4)
portNetProc: ReadConnection.EnumPortNetsProc= {
found: BOOL;
val: REF;
port: REF PortRec;
[found, val] ← r.ports.Fetch[portName];
IF ~ found THEN ERROR IP.Error[missingRegistration, portName];
port ← NARROW[val];
port.net ← netName;
};--portNet--
--(5)
instanceProc: ReadConnection.EnumCompsProc = {
pinNets: LIST OF PinNetRec ← NIL;
instType: REF TypeRec;
WHILE pinNetList #
NIL
DO
pN: RC.pinNet ← pinNetList.first;
pinNets ← CONS[PinNetRec[pN.pinName, pN.netName], pinNets];
pinNetList ← pinNetList.rest;
ENDLOOP;
IF ~ r.instances.Insert[instName,
NEW[InstanceRec ← [typeName, pinNets]]]
THEN ERROR IP.Error[doubleRegistration, instName];
BEGIN
found: BOOL ← FALSE;
val: REF;
cdObj: CD.Object;
ipType: REF TD.TypeEntryRep;
[found, val] ← r.types.Fetch[typeName];
IF found
THEN {
instType ← NARROW[val];
instType.instances ← CONS[instName, instType.instances];
RETURN --Done
}; --endIF
IF chipBeforeTyp
THEN {
IF cdDesign # NIL THEN [found, cdObj]← CDDirectory.Fetch[cdDesign, typeName];
IF found
THEN {
-- CDPins.CleanUpPins[cdDesign, cdObj];
instType ← FromCDType[cdObj, instName];
GOTO insert;
}; --endIF
IF ipTypDict # NIL THEN [found, ipType] ← ipTypDict.LookUp[typeName];
IF found
THEN {
instType ← FromIPType[ipType, instName];
GOTO insert;
}; --endIF
}
ELSE {
IF ipTypDict # NIL THEN [found, ipType] ← ipTypDict.LookUp[typeName];
IF found
THEN {
instType ← FromIPType[ipType, instName];
GOTO insert;
}; --endIF
IF cdDesign #NIL THEN [found, cdObj] ← CDDirectory.Fetch[cdDesign, typeName];
IF found
THEN {
-- CDPins.CleanUpPins[cdDesign, cdObj];
instType ← FromCDType[cdObj, instName];
GOTO insert;
}; --endIF
}; --endIF
TerminalIO.WriteRope[Rope.Cat[typeName, " is undefined\n"]]
EXITS
insert => [] ← r.types.Insert[typeName, instType];
END;
};--instanceProc--
--(A) Read in all type definitions into r.types if debug = TRUE
-- NB: precedence specified by chipBeforeTyp
IF debug
THEN {
eachTypAction: IPTypeDict.EachTypeEntryAction ={
[] ← r.types.Insert[type, FromIPType[entry]]
}; --eachTypAction
eachCDObjAction: CDDirectory.EachEntryAction ={
-- CDPins.CleanUpPins[cdDesign, ob];
[] ← r.types.Insert[name, FromCDType[ob]]
}; --eachCDObjAction
IF chipBeforeTyp
THEN {
IF cdDesign # NIL THEN [] ← CDDirectory.Enumerate[cdDesign, eachCDObjAction];
IF ipTypDict # NIL THEN [] ← IPTypeDict.TypeEntries[ipTypDict, eachTypAction];
}
ELSE {
IF ipTypDict # NIL THEN [] ← IPTypeDict.TypeEntries[ipTypDict, eachTypAction];
IF cdDesign # NIL THEN [] ← CDDirectory.Enumerate[cdDesign, eachCDObjAction];
}; --endIF
}; --endIF
--(B) Read Connections: (i) roseFile (ii) chipFile and/or typeFile
RC.ReadConct[roseFile, headerProc, portsProc, netProc, portNetProc, instanceProc];
--(C) Read initFile, that is the initial placement of components
IF initFile #
NIL
THEN {
stream: IO.STREAM ← FS.StreamOpen[initFile];
DO
ENABLE IO.EndOfStream => EXIT;
token: ATOM ← TB.GetIdAtom[stream];
SELECT token
FROM
$initialPlacement => GetInitialPlacement[r.instances, stream]
ENDCASE => {
TerminalIO.WriteRope[Rope.Cat["Unknown Token: ", Atom.GetPName[token]]];
TB.RemoveBlock[stream];
TerminalIO.WriteRope["\n\t Associated block is ignored"];
};
ENDLOOP;
}; --endIF
RETURN [r]
}; --CreateFrom--
Fetch:
PUBLIC
PROC[r: Ref, name: Rope.
ROPE, what: Which]
RETURNS [val:
REF] ={
found: BOOL;
whatTable: SymTab.Ref ←
SELECT what
FROM
net => r.nets,
port => r.ports,
type => r.types,
instance => r.instances,
ENDCASE => ERROR;
[found, val] ← whatTable.Fetch[name];
IF found
THEN RETURN [val]
ELSE ERROR IP.Error[missingRegistration, name];
}; --Fetch--
Nets:
PUBLIC
PROC[r: Ref, action: EachNetAction] ={
netProc: SymTab.EachPairAction = {
RETURN [action[key, NARROW[val]]]}; --netProc--
[] ← r.nets.Pairs[netProc];
}; --Nets--
Ports:
PUBLIC
PROC[r: Ref, action: EachPortAction] ={
portProc: SymTab.EachPairAction = {
RETURN [action[key, NARROW[val]]]}; --portProc--
[] ← r.ports.Pairs[portProc];
}; --Ports--
Types:
PUBLIC
PROC [r: Ref, action: EachTypeAction] ={
typeProc: SymTab.EachPairAction = {
RETURN [action[key, NARROW[val]]]}; --typeProc--
[] ← r.types.Pairs[typeProc];
}; --Types--
Instances:
PUBLIC
PROC[r: Ref, action: EachInstanceAction] ={
instanceProc: SymTab.EachPairAction = {
RETURN [action[key, NARROW[val]]]}; --instanceProc--
[] ← r.instances.Pairs[instanceProc];
}; --Instances--
FromCDType:
PROC[cdObj:
CD.Object, firstInst: Rope.
ROPE ←
NIL]
RETURNS [
REF TypeRec] ={
shape: REF ShapeRep;
pins: LIST OF REF IP.PinRep ← TB.IPPinsFromCDPins[cdObj];
cdRect: CD.Rect ← CD.InterestRect[cdObj].r;
origin: IP.IntVector ← [cdRect.x1, cdRect.y1];
width: NAT ← cdRect.x2 - cdRect.x1;
height: NAT ← cdRect.y2 - cdRect.y1;
instances: LIST OF Rope.ROPE ← IF firstInst = NIL THEN NIL ELSE LIST[firstInst];
--Now only determine width and height of cdObj. Dimension of corners may come later
shape ← NEW[ShapeRep ← [BO.NuNatVector [width, height]]];
RETURN [NEW[TypeRec ← [origin, instances, pins, shape]]]
}; --FromCDType--
FromIPType:
PROC [ipType:
REF
TD.TypeEntryRep, firstInst: Rope.
ROPE ←
NIL]
RETURNS [
REF TypeRec] = {
instances: LIST OF Rope.ROPE ← IF firstInst = NIL THEN NIL ELSE LIST[firstInst];
RETURN [NEW[TypeRec ←[ipType.origin, instances, ipType.pins, ipType.shape, ipType.shapeFn, ipType.restriction]]]
}; --FromIPType
GetInitialPlacement:
PROC[instances: SymTab.Ref, stream:
IO.
STREAM] ={
found: BOOL;
val: REF;
TB.EnterBlock[stream];
UNTIL
TB.ExitBlock[stream]
DO
instName: Rope.ROPE ← TB.GetIdRope[stream];
[found, val] ← instances.Fetch[instName];
IF found
THEN {
TB.EnterBlock[stream];
UNTIL TB.ExitBlock[stream]
DO
token: ATOM ← TB.GetIdAtom[stream];
SELECT token
FROM
$origin => NARROW[val, REF InstanceRec].origin ← TB.GetIntVector[stream];
$orient => NARROW[val, REF InstanceRec].orient ← stream.GetInt;
ENDCASE => {
TerminalIO.WriteRope[Rope.Cat["Unknown token: ", Atom.GetPName[token], ". associated value ignored"]];
[] ← stream.GetRefAny;
};
ENDLOOP;
}
ELSE {
TerminalIO.WriteRope[Rope.Cat[instName, " ← Unknown instance. Block is ignored\n"]];
TB.RemoveBlock[stream]
};
ENDLOOP;
}; --GetInitialPlacement
END.