Parquet.mesa
Copyright © 1984 by Xerox Corporation. All rights reserved.
Created by: Mayo, June 8, 1984 12:40:57 pm PDT
Last Edited by: Mayo, September 17, 1984 4:24:27 pm PDT
-- Use Levels to look at this document --
-- Parquet: A VLSI Layout Tiler
-- A program to place cells down by alignment marks on those cells.
-- This program forms the layout portion of many (I hope) module generators.
DIRECTORY
Rope USING [ROPE],
SymTab USING [Ref],
StretchLines USING [LineData],
CDOrient USING [mirrorX, rotate270, rotate180, rotate90, original],
CD USING [Design, ObPtr, Position, Orientation, ApplicationPtr];
Parquet: CEDAR DEFINITIONS =
BEGIN
-- Types
There are several types of data defined by the tiler program:
Tiles: ChipNDale cells that have additional annotations such as alignment marks and stretch lines:
Alignment Marks: Named points used to align tiles
Stretch Lines: Labeled lines used to stretch tiles and mask geometry.
Check Marks: Marks that must be matched up with at least one other mark in the finished module.
NOTE: It is an ERROR to place a tile into more than one ChipNDale Design. If this is must be done, another tile may be created via the InstantiateTile[] procedure. Most module generators can ignore this restriction since they only produce one module per invocation.
PlacedTiles: Tiles that have been placed into a Module at a specific point.
Context: Tells where to put the module once it is done, what design contains the tiles, and the parameters to use in generating the module.
Modules: Collections of tiles that have been assembled.
Each module generator is written as a proc that is registered with the tiler. When invoked, it should look at the variables defined in the passed parameter table and produce a Module. It may return NIL if it couldn't make the module. If all the parameters are not present in the table the generator can prompt for them using the TerminalIO package.
ModuleGeneratorProc: TYPE = PROC[context: Context] RETURNS [Module];
Position: TYPE = CD.Position;    -- a point (x, y pair)
Mark: TYPE = REF MarkRec;    -- an alignment mark on a cell
MarkRec: TYPE = RECORD [
name: Rope.ROPENIL,
pos: Position ← [0, 0],        -- the location of the mark in containing tile
owner: PRIVATE INT ← 0
];
Tile: TYPE = REF TileRec;      -- a cell
TileRec: TYPE =RECORD [
obj: CD.ObPtr,       -- obj.specificRec will be a CD.CellPtr
top, bottom, left, right, ul, ur, ll, lr: Mark ← NIL,   
-- location of 8 common marks (defaults as explained below)
markList: PRIVATE MarkList ← NIL, -- other marks to be retrieved via GetMark[]
exportMarks: PRIVATE MarkList ← NIL,
checkList: PRIVATE CheckList ← NIL,
inheritedErrors: PRIVATE INT ← 0
];
MarkList: TYPE = LIST OF Mark;
CheckList: TYPE = LIST OF CD.Position;
Default Alignment Marks:
8 marks can default: top, bottom, left, right, ul, ur, ll, and lr. The abbreviations stand for "Upper Left Corner", "Upper Right Corner", etc. . They can be specified by the user, but if none are specified they default to the 4 corners of the tile and the middle of the 4 sides. If some are specified, their location influences the defaulting of the rest in the following manner: If user-specified marks are on a side of a tile that contains a mark to be defaulted, then take the common coordinate from the user-specified mark. For instance, if the user specified ul, then the X coordinate for ll would be taken from ul and the Y coordinate set to the bottom of the tile. Likewise, if the user specified ur and bottom, then the X coordinate for lr would be taken from ur and the Y coordinate would be taken from bottom.
PlacedTile: TYPE = REF PlacedTileRec;  -- a cell that has been placed into a design
PlacedTileRec: TYPE = RECORD [
pos: Position,        -- the location of the lower-left corner of the cell
tile: Tile,
orient: Orientation,
owner: Module
]; 
Context: TYPE = REF ContextRec;
ContextRec: TYPE = RECORD [
parameters: SymTab.Ref ← NIL,  -- parameters for the module generator
workingDirectoryToUse: Rope.ROPENIL,
tiles: CD.Design ← NIL,   -- a design containing tiles, MUST be imported by `eventualOwner', normally filled in by Parquet
eventualOwner: CD.Design ← NIL -- a design that will receive the module, filled in by Parquet
];
Module: TYPE = REF ModuleRec;   -- a structure containing placed tiles
ModuleRec: TYPE = RECORD [
valid: PRIVATE BOOLFALSE,
-- modules are invalidated when they are converted to tiles
data: PRIVATE REFNIL
];
Error: ERROR [ec: ErrorCode];
ErrorCode: TYPE = {Null,   -- never raised
NoSuchMark,     -- a bad Mark was passed
NoSuchTile,      -- a bad Tile was passed
NoSuchPlacedTile,    -- a bad PlacedTile was passed
NoSuchTileSet,     -- a bad TileSet was passed
MarkNotInTile,     -- the Mark is not in the specified cell or design
PlacedTileNotInModule,  -- the PlacedTile is not in the specified module
InvalidModule,     -- you attempted to use an invalid module, maybe the module was converted to a tile earlier?
BadArgs       -- something was wrong with the arguments passed
};
-- Orientations
-- Rotations are specified in the COUNTER-clockwise direction
Orientation: TYPE = CD.Orientation ← IdentityOrient; -- a description of rotation and mirroring
IdentityOrient: Orientation ~ CDOrient.original;  -- a no-op orientation
MirrorX: Orientation ~ CDOrient.mirrorX;    -- flip X coordinates
MirrorY: Orientation;          -- flip Y coordinates
Rotate90: Orientation ~ CDOrient.rotate90;    -- rotate counter-clockwise 90 degrees
Rotate180: Orientation ~ CDOrient.rotate180;   -- rotate counter-clockwise 180 degrees
Rotate270: Orientation ~ CDOrient.rotate270;    -- rotate counter-clockwise 270 degrees
InverseOrient: PROC [orient: Orientation] RETURNS [Orientation];
ComposeOrient: PROC [first, second: Orientation] RETURNS [Orientation];
returns an orientation that would have the same effect as first applying 'first' and then applying 'second'
-- (look in CDOrient.mesa, ChipNDale, for more definitions and operations)
-- General procedures
Register a module generator with the tiler, returns TRUE if this is a new generator,
-- and FALSE if it has replaced another generator's command.
-- If needsTiles = FALSE, then module generator must fill in context.tiles itself.
RegisterGenerator: PROC[generatorName: Rope.ROPE, proc: ModuleGeneratorProc, needsTiles: BOOLTRUE] RETURNS [BOOL];
-- Loading in tiles & dealing with parameters
-- Combine the current parameters (from the context variable parameters) with any additional parameters supplied by the generator, with the latter overriding. Then take the parameters from the tile set and put them in the table if those parameters are not already defined. The end result is put in back into context.parameters.
CombineParameters: PROC [context: Context, generatorParameters: SymTab.Ref];
-- Retrieve a fully instantiated cell given it's name and a table of parameters from the context. The variables 'SizeX' and 'SizeY' in the parameter table are filled in with the size of the uninstantiated cell so that the cell may use these as parameters. Some objects in cells (such as stretch lines) look values up in the parameter table passed. The parameter table contains refs to type 'AMTypes.TypedVariable'.
-- This procedure is slow, and therefor should not be called needlessly.
InstantiateTile: PROC [context: Context, cellName: Rope.ROPE] RETURNS [Tile];
-- NIL if not found
-- Creating a module
-- also returns an empty PlacedTile with which to align things via AlignTile
NewModule: PROC [context: Context] RETURNS [module: Module, pc: PlacedTile];
Direction: TYPE = {above, below, rightOf, leftOf};
-- Place a cell next to another, using the "top", "bottom", "left", and "right" alignment marks.
AdjacentTile: PROC [oldTile: PlacedTile, newTile: Tile, dir: Direction, orient: Orientation ← IdentityOrient] RETURNS [PlacedTile];
-- Place a cell next to another, using the "ll" and "lr" alignment marks (for rightOf and leftOf), or the "ll" and "ul" alignment marks (for above and below).
AdjacentTileCorners: PROC [oldTile: PlacedTile, newTile: Tile, dir: Direction, orient: Orientation ← IdentityOrient] RETURNS [PlacedTile];
-- place a cell into a design using alignment marks
AlignTile: PROC [oldTile: PlacedTile, oldMark: Mark, newTile: Tile, newMark: Mark, orient: Orientation ← IdentityOrient] RETURNS [PlacedTile];
-- Place the new cell such that it's mark is aligned with the mark on the old cell.
-- Value returned is the new placed cell.
-- Specifying Hierarchy
-- Switch to a new block in the hierarchy. Subsequent cells will appear in this block. When the generator is done, each block will be put into a chipndale cell. blockName does not have to be declared: if that block doesn't exist a new one is created. The topmost block can be switched to by passing a NIL blockName.
SwitchBlock: PROC [module: Module, blockName: Rope.ROPE];
-- Returns the last rope passed to SwitchBlock for this module.
GetCurrentBlock: PROC [module: Module] RETURNS [Rope.ROPE];
-- Nest one block inside of another. If the block is already nested or if the nesting creates a circularity then the call is ignored and FALSE is returned. The topmost block is refered to by NIL. Unnested blocks will be put in the topmost block.
NestBlock: PROC [module: Module, child, parent: Rope.ROPE] RETURNS [done: BOOL];
-- Dealing with Marks
-- retrieve a mark given it's name
-- Special names: If the mark is named "ul", "ur", "ll", or "lr", and the mark
-- does not exist, a ficticous mark at that corner is returned.
GetMark: PROC [fromTile: Tile, markName: Rope.ROPE] RETURNS [Mark];
-- NIL if not found
-- Place a new alignment mark into a module on top of an existing tiles's mark. The mark goes in the topmost block of the module.
AlignMark: PROC [oldTile: PlacedTile, oldMark: Mark, newMarkName: Rope.ROPE];
-- Operations on Modules
-- Turn a module into a tile, TRASHING the initial module. The module MUST NOT be used again. The module may contain parameterizations such as stretch lines.
-- Name is an arbitrary name that you chose for this tile.
-- IF bbox = TRUE then don't propagate default marks up as described below, just put the default marks on the bounding box of the cell.
-- IF fast = TRUE then don't look for stretch lines, alignment marks, etc. in the cell, and skip the checking of check marks. Default alignment marks will be put on the new tile in as described below.
Computation of marks for the new tile:
+ If any of the tiles in the module had marks ending in '^', then those are propagated up into the new tile, but with the '^' stripped off.
+ The mark 'top' is the highest of all the top marks placed, or the leftmost of those if there is more than one.
+ The mark 'bottom' is the lowest of all the bottom marks placed, or the leftmost of those if there is more than one.
+ The mark 'right' is the rightmost of all the right marks placed, or the lowest of those if there is more than one.
+ The mark 'left' is the leftmost of all the left marks placed, or the lowest of those if there is more than one.
+ The mark 'ul' is the mark with the highest value of (-x + y) of all the ul marks placed, or the leftmost of those if there is more than one.
+ The mark 'ur' is the mark with the highest value of (x + y) of all the ur marks placed, or the rightmost of those if there is more than one.
+ The mark 'll' is the mark with the highest value of (-x + -y) of all the ll marks placed, or the leftmost of those if there is more than one.
+ The mark 'lr' is the mark with the highest value of (x + -y) of all the lr marks placed, or the rightmost of those if there is more than one.
ModuleIntoTile: PROC [module: Module, name: Rope.ROPE, context: Context, fast: BOOLFALSE, bbox: BOOLFALSE] RETURNS [numErrors: INT, tile: Tile];
-- Checks alignment marks to make sure that the ones placed by the tiler match up properly, as indicated by the syntax of the mark name.
-- Return result is the number of errors found, and as a side effect error paint is put in the Module over any problem areas.
CheckModule: PROC [module: Module] RETURNS [INT];
-- Low-level Procedures (Use of these routines is rare, but not unheard of.)
-- place a cell into a design at absolute coordinates
PlaceTile: PROC [into: Module, tile: Tile, lowerLeftCorner: Position, orient: Orientation ← IdentityOrient] RETURNS [PlacedTile];
-- find out the size of a tile
TileSize: PROC [tile: Tile] RETURNS [Position];
-- return position of upper right corner relative to lower-left corner
-- find out the location of an placed cell in a module
PlacedTileLoc: PROC [tile: PlacedTile] RETURNS [xmin, ymin, xmax, ymax: INT];
-- find the absolute coordinates of an alignment mark on a placed cell
PlacedMarkLoc: PROC [oldTile: PlacedTile, oldMark: Mark] RETURNS [Position];
-- Add a check mark to a Module at absolute coordinates. Always goes in the top level of the module.
PlaceCheckMark: PROC [into: Module, markPos: Position];
-- Add an alignment mark to a Module at absolute coordinates. Always goes in the top level of the module.
PlaceMark: PROC [into: Module, markName: Rope.ROPE, markPos: Position];
-- Add a stretch line to a Module at absolute coordinates. Always goes in the top level of the module.
StretchData: TYPE = StretchLines.LineData;
StretchLines.LineData: TYPE = RECORD [
point: CD.Position,   -- left (or lower) endpoint of stretch line
length: INT ← 1,    -- length of line (forced be be equal or greater than some minimum)
direction: LineDirections ← up, -- the direction to stretch in
type: LineTypes ← pointed,  -- type type of object
label: Rope.ROPENIL,   -- the attached label
level: CD.Level ← CD.combined -- The level (or layer) that it refers to. If value is CD.combined and type = blunt and we know what design it is being placed in, then it is set to that design's current default level. Always set to 'combined' for pointed lines
];
PlaceStretch: PROC [into: Module, data: StretchData];
-- General loophole: place arbitrary application into Module
PlaceApplication: PROC [into: Module, aptr: CD.ApplicationPtr];
END.