DIRECTORY
CD USING [CellPtr, Design, Error, ErrorCode, Instance, InterestRect, InterestSize, Layer, Object, Position, Rect, Technology],
CDCells USING [CreateEmptyCell, IncludeMode, IncludeOb, RepositionCell, SetInterestRect],
CDDirectory USING [Include],
CDImports USING [Load, CreateImport],
CDIO USING [MakeName, ReadDesign, WriteDesign],
CDOps USING [CreateDesign],
CDProperties USING [PutPropOnObject, RegisterProperty],
CDRects USING [CreateRect],
CDSil USING [cdsil, xaqua, xbrown, xcyan, xgreen, xlime, xmagenta, xneutral, xorange, xpink, xred, xsmoke, xturquise, xultraviolet, xviolet, xwhite, xyellow],
CDSilConversion,
CDTexts USING [CreateText, FontRec, MakeFont],
CDViewer USING [CreateViewer],
Commander USING [CommandProc, Register],
CommandTool USING [ParseToList],
FileNames USING [CurrentWorkingDirectory],
FS USING [ComponentPositions, Error, ExpandName, Position, StreamOpen],
ImagerFont USING [Extents, Font, RopeBoundingBox],
IO USING [Close, EndOf, EndOfStream, GetChar, STREAM, UnsafeGetBlock],
Real USING [Round],
Rope USING [ActionType, Cat, Concat, FromChar, FromProc, Length, Map, Replace, ROPE, SkipTo, Substr],
TerminalIO USING [WriteChar, WriteInt, WriteLn, WriteRope, UserAbort, Confirm],
UserProfile USING [Token];
CDSilConversionImpl:
CEDAR PROGRAM
IMPORTS CD, CDCells, CDDirectory, CDImports, CDIO, CDOps, CDProperties, CDRects, CDSil, CDTexts, CDViewer, Commander, CommandTool, FileNames, FS, ImagerFont, IO, Real, Rope, TerminalIO, UserProfile
EXPORTS CDSilConversion =
BEGIN OPEN CDSilConversion;
Toggles for behaviour of this program
convLibEachTime: BOOL = FALSE; -- convert all library files for each model
verbose: BOOL = FALSE; -- Asks the user whether he wants to write the converted model and libraries
Toggles for debugging
debug0: BOOL ← FALSE; -- reading file
debug1: BOOL ← FALSE; -- converting
debug2: BOOL ← FALSE; -- integration of macro files
debug3: BOOL ← FALSE; -- main Sil model
debug4: BOOL ← FALSE; -- translation of font names
debugAll: BOOL ← debug0 OR debug1 OR debug2 OR debug3 OR debug4;
Description of the SIL file structure:
The first word in the file is a check code, that can be used to see that the file is actually a Sil format file. This word has two possible values, octal 34562 and 34563. The second value has been adopted as part of the design automation process to indicate that a Sil schematic file has been "build" into a wire-list file via the Build process.
Following this word are a secession of "item blocks" that describe the contents of the Sil drawing. An Item block has the following form:
word 0: macro-code
If this word equals a character code, then this item is to be added to the list of items for the macro Font 4 character. All items which are part of macro definitions will appear first in the file.
word 1: state and X-min
bits 0...3 are used internally to indicate the current state of an item - normal, selected, or deleted.
bits 4...15 are the minimum X coordinate bit position of the bounding box that the item occupies.
word 2: Y-min
bits 0...15 are the minimum Y coordinate bit position of the bounding box that the item occupies.
word 3: color and X-max
bits 0...3 are used to indicate the color associated with this item according to the following table:
00: Neutral 08: Brown
01: Red 09: Orange
02: Yellow 10: Lime
03: Green 11: Turquise
04: Cyan 12: Aqua
05: Violet 13: UltraViolet
06: Magenta 14: Pink
07: White 15: Smoke
bits 4...15 are the maximum X coordinate bit position of the bounding box that the item occupies.
word 4: font, face, and Y-max
bits 0...3 are used to indicate the "font" associated with this item. Font values are interpreted according to the following table:
00: Font 0
01: Font 0 with "boldness" opposite to default value in profile
02: Font 1
03: Font 1 with "boldness" opposite to default value in profile
04: Font 2
05: Font 2 with "boldness" opposite to default value in profile
06: Font 3
07: Font 3 with "boldness" opposite to default value in profile
08: Font 4 macro
09: Font 5 macro
10: Font 6 macro
11: Font 7 macro
12: Font 8 macro
13: Font 9 macro
14: A line with lingth and width indicated by preceeding coordinates
15: A background with area indicated by preceeding coordinates
bit 4 is used to indicate the "italics" opposite to default value in profile. This bit only has significance if the font value is 0 through 7.
bits 5...15 are the maximum Y coordinate bit position of the bounding box that the item occupies.
word 5 etc: optional string
If the preceeding word indicated an item of fonts 0 through 13, then additional words are required to define the characters in the item string. This is done with a BCPL string definition, that is, the left byte of word 5 is the number of characters in the string, the right byte is the first character. Additional words are appended as needed to contain the specified number of character bytes.
All coordinate value are expressed in "Alto Screen" units and are referneced to the upper left hand corner of the screen.
Notice that descriptions of library fonts 5 through 9 characters are not defined within this Sil file. A table is filled in by Sil during input, and later the library files indicated in the user profile are opened, and the front of the file is scanned for items defining the required character codes for each of the library fonts characters.
This boils down to the following Cedar declarations for reading a Sil file.
FourBits: TYPE ~ [0..17B];
TwelveBits: TYPE ~ [0..7777B];
SixteenBits: TYPE ~ [0..177777B];
OneBit: TYPE ~ [0..1];
ElevenBits: TYPE ~ [0..3777B];
bytesInSilItemBlock: NAT ~ 10;
mainElementName: CHAR ~ 377C; -- this as name of silobject means it's part of main picture
checkCodeByte1: CHAR ~ '9; -- check code indicating Sil format
unbuiltCheckCodeByte2: CHAR ~ 'r;
builtCheckCodeByte2: CHAR ~ 's;
largeFormatFileByte2: CHAR ~ 'l; -- new password for large format files
SilBlockRef: TYPE ~ REF SilBlock;
SilBlock:
TYPE ~
MACHINE DEPENDENT RECORD [
leftChar, rightChar: CHAR,
state : FourBits,
xMin : TwelveBits,
yMin : SixteenBits,
color : FourBits,
xMax : TwelveBits,
font : FourBits,
italic : OneBit,
yMax : ElevenBits
];
For convenience we introduce the following font subranges.
TrueFonts: TYPE ~ [0..3];
MainFile: TYPE ~ [4..4];
LibraryFile: TYPE ~ [5..9]; declared in the definitions
SilFile: TYPE ~ [4..9];
InternalFonts: TYPE ~ [0..15];
InternalMacroFonts: TYPE ~ [8..13];
InternalFileMacroFonts: TYPE ~ [8..8];
InternalTrueFonts: TYPE ~ [0..7];
InternalLibraryFile: TYPE ~ [9..13];
InternalRopeFonts: TYPE ~ [0..13]; -- those fonts which do not denote boxes. See below
InternalBoxFonts: TYPE ~ [14..15];
InternalForegroundBoxFonts: TYPE ~ [14..14];
InternalBackgroundBoxFonts: TYPE ~ [15..15];
mainFile: MainFile ~ 4;
internalFileMacroFont: InternalFonts ~ 8;
foregroundBoxFont: InternalFonts ~ 14;
backgroundBoxFont: InternalFonts ~ 15;
Color: TYPE ~ [0..15];
colorTable: ARRAY Color OF CD.Layer ~ [CDSil.xneutral, CDSil.xred, CDSil.xyellow, CDSil.xgreen, CDSil.xcyan, CDSil.xviolet, CDSil.xmagenta, CDSil.xwhite, CDSil.xbrown, CDSil.xorange, CDSil.xlime, CDSil.xturquise, CDSil.xaqua, CDSil.xultraviolet, CDSil.xpink, CDSil.xsmoke];
neutralColor: Color ~ 0;
Storage of fonts.
Font:
TYPE ~
RECORD [
name: Rope.ROPE,
descr: REF READONLY CDTexts.FontRec ← NIL
];
cellFonts: ARRAY InternalTrueFonts OF ARRAY BOOL OF Font;
Storage of macros.
ObjectName: TYPE ~ CHAR[' .. '~]; -- Only printing characters are used
MacroName: TYPE ~ CHAR['! .. '~]; -- All but <space>
mainObject: ObjectName ~ ' ; -- object whose name is <space>
SilObject:
TYPE ~
RECORD [
xMin, yMin: INTEGER, -- Upper Left boundary of box or string
xMax, yMax: INTEGER, -- Lower right boundary of box, guess for lower right of string
color: Color, -- Color used to display or print silobject
font: InternalFonts,
italic: BOOL, -- Only interesting for Ropes (fonts 0-13), TRUE for italic strings
value: Rope.ROPE ← NIL
];
SilObjectList: TYPE ~ LIST OF SilObject;
Macro:
TYPE ~
RECORD [
xMin, yMin: INTEGER ← 32767, -- Upper Left boundary of macro definition
xMax, yMax: INTEGER ← -1, -- Lower right boundary of macro definition
-- note: coordinates are Alto screen absolute, hence -1 is OK.
objects: SilObjectList ← NIL,
cdCellPtr: CD.Object ← NIL -- This field used to generate recursion if a cell includes a cell not known yet.
];
LibraryDesign:
TYPE ~
RECORD [
data: CD.Design ← NIL,
imported: BOOL ← FALSE, -- Chipndale wants only a single import of the same library
written: BOOL ← FALSE -- libraries are written only once per run
];
MacroPtr: TYPE ~ REF Macro ← NIL;
MacroFile: TYPE ~ ARRAY ObjectName OF MacroPtr;
allMacros: REF MacroFile ← NIL;
silDesigns: ARRAY SilFile OF LibraryDesign; -- need all because of imports
background: ATOM = $SilBackground;
silProfilePrefix: Rope.ROPE ~ "Sil.Font";
cdSilProfilePrefix: Rope.ROPE ~ "Chipndale.chipnsil.Library";
lambda: INTEGER = CDSil.cdsil.lambda; -- Sil uses integers throughout
lambdaAltoScreenHeights: INTEGER ~ lambda * 808;
File name towahboo.
CrackNames:
PROC [genericName: Rope.ROPE]
RETURNS [fullSilName: Rope.ROPE, properName: Rope.ROPE] ~ {
Takes any name in any format and produces a full Sil file names in slash convention and a proper name (base). A Chipndale name is not produced because this is already done by Chipndale.
namePos: FS.ComponentPositions;
silExtension: Rope.ROPE ~ "sil";
dummy: Rope.ROPE; -- in Cedar 5.2 FS.ExpandName does not work as documented
fullSilName ← CDIO.MakeName [base: genericName, ext: silExtension, wDir: FileNames.CurrentWorkingDirectory[]];
[fullFName: dummy, cp: namePos] ← FS.ExpandName [name: fullSilName];
properName ← Rope.Substr [base: dummy, start: namePos.base.start, len: namePos.base.length]
}; -- end CrackNames
A small utility.
TechnologyIsCdsil:
PROC [d: CD.Design]
RETURNS [b:
BOOL] ~ {
IF d = NIL THEN CD.Error [explanation: "Programming error in ReadSilLibrary"];
RETURN [d.technology = CDSil.cdsil]
}; -- end TechnologyIsCdsil
Reading a design.
ReadSilModel:
PUBLIC PROC [name: Rope.ROPE]
RETURNS [design: CD.Design ← NIL] ~ {
Reads a file containing a Sil model and makes it avalilable as a Chipndale design 'silDesign' with specific cells 'silDesignCells'.
designName: Rope.ROPE;
write: BOOL ← NOT verbose;
[fullSilName: name, properName: designName] ← CrackNames [name];
IF convLibEachTime
THEN
FOR lib: LibraryFile
IN LibraryFile
DO
Chipndale requires that the libraries be reloaded for every design.
silDesigns[lib].data ← NIL; silDesigns[lib].imported ← FALSE
ENDLOOP;
design ← CDOps.CreateDesign [technology: CDSil.cdsil];
design.name ← designName;
silDesigns[mainFile].data ← design;
ReadSilFile [fileName: name]; ConvertSilFile [file: mainFile];
IF verbose THEN write ← TerminalIO.Confirm [label: "CDSilConversion", choice: Rope.Cat["Write ", designName, " to disk ?"]];
IF write
THEN
IF
NOT
CDIO.WriteDesign [design: design, to: designName]
THEN
TerminalIO.WriteRope [Rope.Cat["Warning: The design ", designName, " cannot be written. Proceeding anyway.\n"]];
[] ← CDViewer.CreateViewer [design: design];
}; -- end ReadSilModel
Reading a library file.
ReadSilLibrary:
PUBLIC
PROC [library: LibraryFile]
RETURNS [cells:
CD.Design ←
NIL] ~ {
Reads all macros from a macro disk file and stores them into the Chipndale cells. The design 'cells' additionally contains a synopsis of the cells it contains. For normal usage, 'cells' is not needed.
libraryPrefix: Rope.ROPE ~ "sil.lb"; -- Cedar Sil
designPrefix: Rope.ROPE ~ "SilLib"; -- Chipnsil
macroFileName, cdFileName, defaultName, designName: Rope.ROPE;
key: Rope.ROPE; -- Access key for the User Profile.
write: BOOL ← NOT verbose;
Libray may already have been converted.
IF silDesigns[library].data # NIL THEN RETURN [silDesigns[library].data];
Build Chipnsil design name.
key ← Rope.Concat [cdSilProfilePrefix, Rope.FromChar['0 + library]];
defaultName ← Rope.Cat [designPrefix, Rope.FromChar['0 + library], ".dale"];
cdFileName ← UserProfile.Token [key: key, default: defaultName];
designName ← CrackNames [cdFileName].properName;
Build the Sil library name.
key ← Rope.Concat [silProfilePrefix, Rope.FromChar['0 + library]];
defaultName ← Rope.Concat [libraryPrefix, Rope.FromChar['0 + library]];
macroFileName ← UserProfile.Token [key: key, default: defaultName];
IF
NOT convLibEachTime
THEN
BEGIN
Check whether the library file already exists in Chipndale format and read it if this is the case.
cells ← CDIO.ReadDesign [from: cdFileName, check: TechnologyIsCdsil];
IF cells # NIL THEN {silDesigns[library].data ← cells; RETURN [cells]}
ELSE
TerminalIO.WriteRope [Rope.Cat["The library file ", cdFileName, " is not available. It is being converted from ", macroFileName, "\n"]];
END; -- NOT convLibEachTime
Read in the the library file specified and convert it.
ReadSilFile [fileName: macroFileName];
cells ← CDOps.CreateDesign[technology: CDSil.cdsil];
cells.name ← designName;
silDesigns[library].data ← cells;
ConvertSilFile [file: library];
Write the library to disk, if necessary.
IF verbose THEN write ← TerminalIO.Confirm[label: "CDSilConversion", choice: Rope.Cat["Write ", designName, " to disk ?"]];
IF write
THEN {
IF
NOT silDesigns[library].written
THEN {
silDesigns[library].written ← CDIO.WriteDesign [design: cells, to: cdFileName];
IF
NOT silDesigns[library].written
THEN
TerminalIO.WriteRope [Rope.Cat["Warning: The design ", designName, " cannot be written. Proceeding anyway.\n"]]
}
}; -- IF write
RETURN [cells]
}; -- end ReadSilLibrary
SetFonts:
PROC [] ~ {
Gets from the user profile the fonts and makes the names for the Chipndale fonts. For the moment we consider only the display font, as Cedar Sil does. The chipndale fonts are made only when they are referenced the first time.
key: Rope.ROPE; -- Access key for the User Profile.
TrueFontsDefaults: TYPE ~ ARRAY TrueFonts OF Rope.ROPE;
trueFontsDefaults: TrueFontsDefaults ~ ["Helvetica10", "Helvetica7", "Template64", "Gates32"];
italic: BOOL ~ TRUE;
FixAttibutes:
PROC [coarseName: Rope.ROPE]
RETURNS [notBold, italic, both: Rope.ROPE] ~ {
Takes the coarse name as it is specified in the user profile, and produces one with the 'bold' (B) attribute reversed as well as one with the 'italic' (I) attibute. The 'narrow' (N) attribute is ignored.
properName, dummy, attributes, notBAttr: Rope.ROPE;
namePos: FS.ComponentPositions;
attributePos, bPos: INTEGER;
alreadyItalic: BOOL;
[fullFName: dummy, cp: namePos] ← FS.ExpandName [name: coarseName];
properName ← Rope.Substr [base: dummy, start: namePos.base.start, len: namePos.base.length];
attributePos ← properName.SkipTo [0, "0123456789"];
attributes ← properName.Substr [attributePos, properName.Length[]-attributePos];
Fix boldness attribute.
bPos ← attributes.SkipTo [0, "bB"];
IF bPos = attributes.Length[] THEN notBAttr ← Rope.Concat [attributes, "B"]
ELSE notBAttr ← Rope.Replace [base: attributes, start: bPos, len: 1];
Add an italic attribute if none is present.
alreadyItalic ← (attributes.SkipTo [0, "iI"] # attributes.Length []);
IF NOT alreadyItalic THEN attributes ← Rope.Concat [attributes, "I"];
Build the new font names.
notBold ← Rope.Replace [base: properName, start: attributePos, len: properName.Length[]-attributePos, with: notBAttr];
italic ← Rope.Replace [base: properName, start: attributePos, len: properName.Length[]-attributePos, with: attributes];
IF alreadyItalic THEN both ← notBold
ELSE {
notBAttr ← Rope.Concat [notBAttr, "I"];
both ← Rope.Replace [base: properName, start: attributePos, len: properName.Length[]-attributePos, with: notBAttr]
};
IF debug4
THEN {
TerminalIO.WriteRope [Rope.Cat["Original font: ", coarseName, ", notBold: "]];
TerminalIO.WriteRope [Rope.Cat[notBold, ", italic: ", italic]];
TerminalIO.WriteRope [Rope.Cat[", both: ", both, "\n"]];
}
}; -- end FixAttibutes
FOR i: TrueFonts
IN TrueFonts
DO
Get the true font names from the profile.
key ← Rope.Concat [silProfilePrefix, Rope.FromChar ['0 + i]];
cellFonts[2*i][~italic].name ← UserProfile.Token [key: key, default: trueFontsDefaults[i]];
[cellFonts[2*i+1][~italic].name, cellFonts[2*i][italic].name, cellFonts[2*i+1][italic].name] ← FixAttibutes [cellFonts[2*i][~italic].name];
ENDLOOP
}; -- end SetFonts
MakeCDFont:
PROC [nr: InternalTrueFonts, italic:
BOOL] ~ {
fullName: Rope.ROPE;
fullName ← Rope.Cat ["Xerox/TiogaFonts/", cellFonts[nr][italic].name];
cellFonts[nr][italic].descr ← CDTexts.MakeFont[name: fullName, scale: lambda];
IF cellFonts[nr][italic].descr =
NIL THEN {
TerminalIO.WriteRope [Rope.Cat["CDTexts.MakeFont returns not found on ", fullName, ". Fatal error.\n"]];
ERROR ABORTED
}
}; -- end MakeCDFont
ConvertSilFile:
PROC [file: SilFile] ~ {
Transforms all Sil macros to Chipndale cells. If a macro contains a macro from another macro file, the following policy is adopted: We try to import it an abort if we fail to do so.
MacroToObject:
PROC [sil: MacroPtr, name: ObjectName]
RETURNS [object: CD.Object ←
NIL] ~ {
Produces a Chipndale object from a Sil macro. The return parameter is necessary for the recursion.
size, position: CD.Position ← [0, 0];
topLeftPos: CD.Position ← [0, 0];
cdObPtr: CD.Object ← NIL; -- object before it is either a cell or an application
cell: CD.Object ← NIL; -- NIL when object is not a cell
boundingBox: CD.Rect; -- interesting rectangle
height: INTEGER ← 0; -- height of cell or main object
import, workingOnMainObject: BOOL;
impName: Rope.ROPE; -- global importee name assigned in FOR loop and used in ExpandRope
ExpandRope:
PROC [c:
CHAR]
RETURNS [quit:
BOOL ←
FALSE] ~ {
TYPE = ActionType.
cdObPtr: CD.Object; -- object before it is either a cell or an application
sz, pos: CD.Position;
IF import
THEN
BEGIN
Imports a string of cells from another library. It is guaranteed that the library is already imported.
cdObPtr ← CDImports.CreateImport[into: silDesigns[file].data, objectName: Rope.FromChar[c], importeeName: impName];
IF cdObPtr =
NIL
THEN
CD.Error [ec: other, explanation: "CDImports.CreateImport failed"];
THIS ERROR REALLY MIGHT HAPPEN
END
ELSE
-- not import: file macro
A file macro is one that is not in a library file, but rather in the file containing the Sil model. Externally it is referred to as a character of font 4.
IF allMacros[c]
.cdCellPtr =
NIL THEN {
IF debug1
THEN {
TerminalIO.WriteRope [" will prepone macro "];
TerminalIO.WriteChar [c]; TerminalIO.WriteLn[]
};
cdObPtr ← MacroToObject [allMacros[c], c];
}
ELSE cdObPtr ← allMacros[c].cdCellPtr;
sz ← CD.InterestSize[cdObPtr];
pos ← [topLeftPos.x, topLeftPos.y-sz.y];
topLeftPos.x ← topLeftPos.x + sz.x;
[] ← CDCells.IncludeOb [design: silDesigns[file].data, cell: cell, ob: cdObPtr, position: pos, obCSystem: interrestCoords, mode: dontPropagate];
}; -- end ExpandRope
workingOnMainObject ← (name = ' );
height ←
IF workingOnMainObject
THEN lambdaAltoScreenHeights
ELSE lambda * (sil.yMax - sil.yMin);
boundingBox ← [x1: lambda*sil.xMin, y1: height - lambda*sil.yMax, x2: lambda*sil.xMax, y2: height - lambda*sil.yMin];
IF workingOnMainObject THEN cell ← NIL
ELSE {
ir: CD.Rect ← [x1: lambda*sil.xMin, y1: height - lambda*sil.yMax, x2: lambda*sil.xMax, y2: height - lambda*sil.yMin];
cell ← CDCells.CreateEmptyCell[];
CDCells.SetInterestRect[cell, ir];
IF debug2
AND ((name = 'B)
OR (name = 'x))
THEN {
TerminalIO.WriteRope ["SetInterestRect to "];
TerminalIO.WriteInt [boundingBox.x1]; TerminalIO.WriteInt [boundingBox.y1];
TerminalIO.WriteInt [boundingBox.x2]; TerminalIO.WriteInt [boundingBox.y2];
TerminalIO.WriteLn
}
};
FOR silObj: SilObjectList ← sil.objects, silObj.rest
WHILE silObj #
NIL
DO
size.x ← lambda * (silObj.first.xMax - silObj.first.xMin);
size.y ← lambda * (silObj.first.yMax - silObj.first.yMin);
topLeftPos.x ← position.x ← lambda * silObj.first.xMin;
position.y ← height - lambda * silObj.first.yMax;
topLeftPos.y ← height - lambda * silObj.first.yMin;
SELECT silObj.first.font
FROM
IN InternalTrueFonts => {
cdFont: REF READONLY CDTexts.FontRec;
er: ImagerFont.Extents;
IF (cellFonts[silObj.first.font][silObj.first.italic].descr =
NIL)
THEN
MakeCDFont [silObj.first.font, silObj.first.italic];
cdFont ← cellFonts[silObj.first.font][silObj.first.italic].descr;
cdObPtr ← CDTexts.CreateText [text: silObj.first.value, font: cdFont, layer: colorTable[silObj.first.color]];
IF cdObPtr = NIL THEN CD.Error [ec: other, explanation: "Cannot create text"];
IF debug2
AND ((name = 'B)
OR (name = 'x))
THEN {
TerminalIO.WriteRope [Rope.Concat ["Value, scendent and y position: ", silObj.first.value]];
TerminalIO.WriteInt [position.y];
TerminalIO.WriteLn []
};
er ← ImagerFont.RopeBoundingBox [cdFont.font, silObj.first.value];
position.y ← height - lambda * silObj.first.yMin - Real.Round[er.ascent] - cdFont.origin.y;
[] ← CDCells.IncludeOb [design: silDesigns[file].data, cell: cell, ob: cdObPtr, position: position, obCSystem: cdCoords, mode: dontPropagate]
};
IN InternalFileMacroFonts => {
IF debug1
THEN {
TerminalIO.WriteChar [name];
TerminalIO.WriteRope [" calls a cell in the same design:\n"]
};
import ← FALSE;
[] ← Rope.Map [base: silObj.first.value, action: ExpandRope]
};
IN InternalLibraryFile => {
Import cell from specified design.
externalFileNr: LibraryFile; -- Since the exported procedure works with the external library file numbering, we cannot use the internal Sil numbering when we call our procedures.
IF debug1
THEN
TerminalIO.WriteRope ["Import of a cell in another design.\n"];
externalFileNr ← silObj.first.font - mainFile;
IF (silDesigns[externalFileNr].data = NIL) THEN [] ← ReadSilLibrary [externalFileNr];
IF
NOT silDesigns[externalFileNr].imported
THEN {
silDesigns[externalFileNr].imported ← CDImports.Load[into: silDesigns[file].data, importeeName: silDesigns[externalFileNr].data.name];
IF
NOT silDesigns[externalFileNr].imported
THEN
IF file
IN MainFile
THEN
CD.Error [ec: other, explanation: "Cannot import library"]
ELSE CD.Error [ec: other, explanation: "Library tried to import other library"]
};
impName ← silDesigns[externalFileNr].data.name; -- assigned to a global variable, so that it can be used inside ExpandRope
import ← TRUE;
[] ← Rope.Map [base: silObj.first.value, action: ExpandRope]
};
IN InternalForegroundBoxFonts => {
cdObPtr ← CDRects.CreateRect [size: size, l: colorTable[silObj.first.color]];
[] ← CDCells.IncludeOb [design: silDesigns[file].data, cell: cell, ob: cdObPtr, position: position, obCSystem: interrestCoords, mode: dontPropagate]
};
IN InternalBackgroundBoxFonts => {
Sil first displays all background rectangles, then the foreground rectangles.
cdObPtr ← CDRects.CreateRect [size: size, l: colorTable[silObj.first.color]];
CDProperties.PutPropOnObject [onto: cdObPtr, prop: background, val: background];
[] ← CDCells.IncludeOb [design: silDesigns[file].data, cell: cell, ob: cdObPtr, position: position, obCSystem: interrestCoords, mode: dontPropagate]
};
ENDCASE => CD.Error [explanation: "Invalid case in CDSilConversionImpl.MacroToObject"]
ENDLOOP;
IF
NOT workingOnMainObject
THEN {
ir: CD.Rect;
NARROW [cell.specificRef, CD.CellPtr].simplifyOn ← height / (2 * lambda);
[] ← CDCells.RepositionCell [cellOb: cell, design: NIL];
ir ← CD.InterestRect [cell];
ir.x2 ← ir.x1+cell.size.x;
CDCells.SetInterestRect [cell, ir];
[] ← CDDirectory.Include [design: silDesigns[file].data, object: cell, alternateName: Rope.FromChar[name]];
};
object ← IF workingOnMainObject THEN cdObPtr ELSE cell;
sil.cdCellPtr ← object;
sil.objects ← NIL; -- dispose obsolete space
IF debug1
THEN {
TerminalIO.WriteRope ["Converted object "];
TerminalIO.WriteChar [name]; TerminalIO.WriteLn[]
};
RETURN [object]
}; -- end MacroToObject
To avoid unnecessary recursion, we convert first the true macros and last the main object.
FOR obj: MacroName
IN MacroName
DO
IF ((allMacros[obj] #
NIL)
AND (allMacros[obj]
.cdCellPtr =
NIL))
THEN
The macro is not empty and has not been converted yet.
[] ← MacroToObject [allMacros[obj], obj]
ENDLOOP;
IF ((allMacros[mainObject] #
NIL)
AND (allMacros[mainObject]
.cdCellPtr =
NIL))
THEN
The mainObject is not empty and has not been converted yet.
[] ← MacroToObject [allMacros[mainObject], mainObject];
IF debugAll THEN TerminalIO.WriteRope ["Sil macro file converted to Chipndale model\n"]
}; -- end ConvertSilFile
ReadSilFile:
PROC [fileName: Rope.ROPE]
~ {
Reads a single macro file.
sBlock: SilBlockRef ← NEW [SilBlock];
AddItemBlockToMacro:
PROC [itemBlock: SilObject, name:
CHAR]
~ {
m: MacroPtr ← allMacros[name];
IF m = NIL THEN m ← NEW [Macro];
Update bounding box of macro.
m.xMin ← MIN [m.xMin, itemBlock.xMin];
m.yMin ← MIN [m.yMin, itemBlock.yMin];
m.xMax ← MAX [m.xMax, itemBlock.yMax];
m.yMax ← MAX [m.yMax, itemBlock.yMax];
Attach item block to Sil object list
m.objects ← CONS [itemBlock, m.objects];
allMacros[name] ← m
}; -- end AddItemBlockToMacro
ReadItemBlock:
PROC [s:
IO.STREAM]
RETURNS [name: CHAR, itemBlock: SilObject]
~ {
Return the Sil item block which appears next in the file being read. Also, return the item block's name, which will be ' (space) for main pictures, and a printing character for item blocks which are part of macro definitions.
ENABLE IO.EndOfStream => CD.Error [ec: other, explanation: "Unexpected End Of Stream"];
ReadChar:
PROC[]
RETURNS [c:
CHAR]
~ {
This procedure exists so it can be passed to Rope.FromProc, below.
RETURN [s.GetChar[] ];
}; -- end ReadChar
Main of ReadItemBlock
maxRecLen: INTEGER ~ 256; --the longest a record can be (1 byte for its length)
len: INTEGER;
TRUSTED {
bytesGot:
INT ← s.UnsafeGetBlock[
[base: LOOPHOLE[sBlock], startIndex: 0, count: bytesInSilItemBlock]
];
IF bytesGot # bytesInSilItemBlock
THEN
CD.Error [ec: other, explanation: "Macro file corrupted"]
};
name ←
IF sBlock.leftChar = mainElementName
THEN '
ELSE sBlock.rightChar;
-- name depends on whether is part of main picture ot macro.
-- state of item block (normal, selected, deleted) is ignored.
itemBlock.xMin ← sBlock.xMin;
itemBlock.yMin ← sBlock.yMin;
itemBlock.xMax ← sBlock.xMax;
itemBlock.yMax ← sBlock.yMax;
itemBlock.color ← sBlock.color;
itemBlock.font ← sBlock.font;
itemBlock.italic ← (sBlock.italic = 1);
IF debug0
THEN {
TerminalIO.WriteLn; TerminalIO.WriteChar [name];
TerminalIO.WriteInt [ORD[name]];
{OPEN itemBlock;
TerminalIO.WriteRope [": xMin, yMin:"];
TerminalIO.WriteInt [xMin]; TerminalIO.WriteInt [yMin];
TerminalIO.WriteRope [". xMax, yMax:"];
TerminalIO.WriteInt [xMax]; TerminalIO.WriteInt [yMax];
TerminalIO.WriteRope [". Col:"]; TerminalIO.WriteInt [color];
TerminalIO.WriteRope [". Font:"]; TerminalIO.WriteInt [font];
IF color # 0 THEN TerminalIO.WriteRope ["***"];
IF NOT italic THEN TerminalIO.WriteRope [", not"];
TerminalIO.WriteRope [" italic "];
}
};
IF itemBlock.font
IN InternalRopeFonts
THEN {
len ← s.GetChar[] - 0C;
itemBlock.value ← Rope.FromProc [len, ReadChar, maxRecLen];
IF debug0 THEN TerminalIO.WriteRope [itemBlock.value];
IF len
MOD 2 = 0
THEN
--Make sure to start next item block on a word boundary
[] ← s.GetChar[]; --Flush the extra slot for a Char
}
}; -- end ReadItemBlock
{
header1, header2: CHAR;
s:
IO.STREAM ← FS.StreamOpen [fileName !
FS.Error =>
IF error.group#bug
THEN {
TerminalIO.WriteRope [Rope.Cat [fileName, " not opened: ", error.explanation]];
ERROR ABORTED
}
];
name: CHAR; itemBlock: SilObject;
IF debugAll
THEN {
TerminalIO.WriteRope [fileName]; TerminalIO.WriteLn
};
header1 ← s.GetChar[]; header2 ← s.GetChar[];
IF (header1 = checkCodeByte1)
AND (header2 = unbuiltCheckCodeByte2)
THEN {
IF debugAll THEN TerminalIO.WriteRope ["Sil file format OK.\n"]
}
ELSE
IF (header1 = checkCodeByte1)
AND (header2 = builtCheckCodeByte2)
THEN
TerminalIO.WriteRope ["Sil schematic file has been 'build' into a wire-list file via the Build process.\n"]
ELSE
IF header2 = largeFormatFileByte2
THEN {
TerminalIO.WriteRope ["Large format files not yet implemented. ABORTED\n"];
ERROR ABORTED
}
ELSE TerminalIO.WriteRope ["File not in Sil format. Proceeding anyway.\n"];
allMacros ← NEW [MacroFile];
WHILE
NOT s.EndOf[]
DO
[name, itemBlock] ← ReadItemBlock [s];
The item block can now be attached to the relative macro. We cannot work directly with cells, because we need the bounding box of the entire macro to convert the y coordinate.
AddItemBlockToMacro [itemBlock, name]
Each library file contains a synopsis of all macros, stored as a main picture.
ENDLOOP;
IO.Close[s]
}
}; -- end ReadSilFile
ReadModel: Commander.CommandProc =
BEGIN
ENABLE {
TerminalIO.UserAbort => GOTO UserAbrt;
};
list: LIST OF Rope.ROPE;
length: NAT;
name: Rope.ROPE;
[list, length] ← CommandTool.ParseToList [cmd];
IF length = 1 THEN name ← list.first
ELSE {
result ← $Failure;
msg ← "unknown arguments";
TerminalIO.WriteRope ["Read command failed\n"];
RETURN
};
IF convLibEachTime THEN TerminalIO.WriteRope ["All libraries will be converted as they are referenced.\n"]
ELSE TerminalIO.WriteRope ["If they exist, the libraries specified in the user profile entries 'ChipNDale.ChipNSil.Library%' will be used. Delete them to force the creation of new ones.\n"];
[] ← ReadSilModel [name];
For library files this would be
synopsis ← ReadSilLibrary [5];
[] ← CDViewer.CreateViewer [design: synopsis]; CDOps.Redraw [synopsis] -- optional
EXITS
UserAbrt => {TerminalIO.WriteRope ["Read aborted\n"]};
END;
Module initialization.
SetFonts[];
IF NOT CDProperties.RegisterProperty [prop: background, registrationKey: $GBB] THEN TerminalIO.WriteRope ["CDSilConversionImpl re-executed"]; -- somebody is already using it
Commander.Register [key: "CDReadSil", proc: ReadModel, doc: "Read a SIL model into ChipNSil and save it"]