<> <> <> <> <<>> <<-- 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 >> <> <<>> <> <> <> <> <<>> <> <<>> <> <<>> <> <<>> <> <<>> <<>> <> 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.ROPE _ NIL, 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; <> <<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.ROPE _ NIL, 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 BOOL _ FALSE, <<-- modules are invalidated when they are converted to tiles>> data: PRIVATE REF _ NIL ]; 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]; <> <<-- (look in CDOrient.mesa, ChipNDale, for more definitions and operations)>> <<-- General procedures>> <<>> <> <<-- 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: BOOL _ TRUE] 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.>> <> <<+ 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: BOOL _ FALSE, bbox: BOOL _ FALSE] 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; <> <> <> <> <> <> <> <<];>> PlaceStretch: PROC [into: Module, data: StretchData]; <<-- General loophole: place arbitrary application into Module>> PlaceApplication: PROC [into: Module, aptr: CD.ApplicationPtr]; END.