File: ParquetImplB.mesa   
Copyright © 1984 by Xerox Corporation. All rights reserved.
Created by: Mayo, July 16, 1984 4:44:25 pm PDT
Last Edited by: Mayo, November 5, 1984 7:10:22 pm PST
Last Edited by: Jacobi, December 20, 1984 9:29:16 am PST
-- ChipNDale user interface routines
DIRECTORY
Parquet,
ParquetInternal,
CDMenus USING [CreateEntry, GetMenu, CreateMenu, ImplementMenuCommand],
StretchLines,
Commander USING [CommandProc, Register],
TerminalIO USING [WriteRope, WriteInt, RequestRope, UserAbort, UserSaysYes],
ExprRead,
CDIO USING [WriteDesign, ReadDesign, GetWorkingDirectory, SetWorkingDirectory],
CDSequencer USING [Command, ImplementCommand],
CD,
CDOps USING [AddAnObject, CreateDesign],
CDImports USING [Import, GetImport, DoImport],
Rope USING [ROPE, Equal, Cat, IsEmpty],
FileNames USING [CurrentWorkingDirectory],
FS USING [FileInfo, ExpandName, Error],
Process USING [SetPriority, priorityBackground],
SymTab USING [Ref, Create, Fetch, Pairs, Store, EachPairAction];
ParquetImplB: CEDAR PROGRAM    
IMPORTS CD, CDMenus, ExprRead, Commander, TerminalIO, CDIO, CDOps, CDImports, Rope, CDSequencer, SymTab, FileNames, FS, Process, Parquet, ParquetInternal EXPORTS Parquet = BEGIN OPEN Parquet, ParquetInternal;
generatorTable: SymTab.Ref;
GeneratorRec: TYPE = RECORD [
proc: ModuleGeneratorProc,
needsTiles: BOOLTRUE
];
markScale: INT = 2;
markWidth: INT = 16;
markHeight: INT = 6;
arrowSize: INT = 4;
-- Top-level command routines
-- register a module generator with the tiler
RegisterGenerator: PUBLIC PROC[generatorName: Rope.ROPE, proc: ModuleGeneratorProc, needsTiles: BOOL] RETURNS [BOOL] = BEGIN
ptr: REF GeneratorRec ~ NEW[GeneratorRec ← [proc: proc, needsTiles: needsTiles]];
RETURN[SymTab.Store[generatorTable, generatorName, ptr]];
END;
ProduceModule: PROC[context: Context, intoPos: CD.Position, fromFile: BOOL] RETURNS [BOOL]= BEGIN   
ENABLE {
TerminalIO.UserAbort => GOTO abort;
CD.Error => BEGIN
TerminalIO.WriteRope["\nChipNDale raised an error flag: '"];
TerminalIO.WriteRope[explanation];
TerminalIO.WriteRope["'\n"];
-- let the system slide into the debugger
END;
ExprRead.Error => {
TerminalIO.WriteRope[msg];
TerminalIO.WriteRope["'\n"];
GOTO abort;
};
};
PrintGenerator: SymTab.EachPairAction = BEGIN
-- PROC [key: Key, val: Val] RETURNS [quit: BOOL]
TerminalIO.WriteRope[" "];
TerminalIO.WriteRope[key];
TerminalIO.WriteRope["\n"];
RETURN[FALSE];
END;
generatorName: Rope.ROPE;
needsTiles: BOOL;
found: BOOL;
generatorProc: ModuleGeneratorProc;
module: Module;
mod: Mod;
tilesName: Rope.ROPENIL;
cellName: Rope.ROPE;
errs: INT;
IF context = NIL OR context.eventualOwner = NIL THEN ERROR;
-- Find the name of the module generator
IF fromFile THEN {
ok: BOOLFALSE;
badFile: BOOLFALSE;
errorMsg: Rope.ROPENIL;
inFile: Rope.ROPE;
-- get file name
inFile ← TerminalIO.RequestRope[Rope.Cat["\nEnter name of a file describing the module (", context.workingDirectoryToUse, ") : "]];
inFile ← FS.ExpandName[inFile, context.workingDirectoryToUse].fullFName;
[] ← FS.FileInfo[inFile !FS.Error => IF error.group = user THEN {
badFile ← TRUE; CONTINUE }];
IF badFile THEN BEGIN
TerminalIO.WriteRope[Rope.Cat["Could not open file '", inFile, "'.\n"]];
GOTO abort;
END;
-- read file
errorMsg ← NIL;
context.parameters ← ExprRead.ReadFile[inFile ! ExprRead.Error => {errorMsg ← msg; CONTINUE}];
IF errorMsg # NIL THEN {
TerminalIO.WriteRope["Error while reading file: '"];
TerminalIO.WriteRope[errorMsg];
TerminalIO.WriteRope["'.\n"];
GOTO abort;
};
-- get ModuleGenerator name
generatorName ← ExprRead.FetchRope[context.parameters, "ModuleGenerator", TRUE ! ExprRead.Error => {errorMsg ← msg; CONTINUE}].val;
IF errorMsg # NIL THEN {
TerminalIO.WriteRope["Error while reading file: '"];
TerminalIO.WriteRope[errorMsg];
TerminalIO.WriteRope["'.\n"];
GOTO abort;
};
IF generatorName = NIL THEN {
TerminalIO.WriteRope["File does not include a 'ModuleGenerator ← xxx' line.\n"];
GOTO abort;
};
}
ELSE {
generatorName ← TerminalIO.RequestRope["\nEnter name of a module generator: (hit return for options) "];
IF Rope.Equal[generatorName, ""] THEN BEGIN
TerminalIO.WriteRope["These generators are currently running:\n"];
[] ← SymTab.Pairs[generatorTable, PrintGenerator];
TerminalIO.WriteRope[" --------\n"];
RETURN[FALSE];
END;
};
-- Find the module generator given its name
{
ptr: REF ANY;
genRef: REF GeneratorRec;
[found, ptr] ← SymTab.Fetch[generatorTable, generatorName];
IF ~found THEN BEGIN
TerminalIO.WriteRope["Module generator '"];
TerminalIO.WriteRope[generatorName];
TerminalIO.WriteRope["' is not currently running.\n"];
GOTO abort;
END;
genRef ← NARROW[ptr];
generatorProc ← genRef.proc;
needsTiles ← genRef.needsTiles;
};
-- Get the tiles, if needed
IF needsTiles THEN {
IF fromFile THEN {
-- get TileSet import name
errorMsg: Rope.ROPENIL;
IF context.tiles = NIL THEN {
tilesName ← ExprRead.FetchRope[context.parameters, "TileSet", TRUE ! ExprRead.Error => {errorMsg ← msg; CONTINUE}].val;
IF errorMsg # NIL THEN {
TerminalIO.WriteRope["Could not read TileSet parameter: '"];
TerminalIO.WriteRope[errorMsg];
TerminalIO.WriteRope["'.\n"];
GOTO abort;
};
};
IF tilesName = NIL THEN {
TerminalIO.WriteRope["File does not include a 'TileSet ← xxx' line.\n"];
GOTO abort;
};
}
ELSE {
IF context.tiles = NIL THEN {
tilesName ← TerminalIO.RequestRope["\nEnter name of the imported design containing the tiles: \n(hit return for the top-level design, or type the name of an imported design) "];
};
};
-- Find the tile set given the name
IF context.tiles = NIL THEN {
IF Rope.IsEmpty[tilesName] THEN
context.tiles ← context.eventualOwner
ELSE {
import: REF CDImports.Import ← CDImports.GetImport[context.eventualOwner, tilesName, $false];
IF import = NIL THEN {
TerminalIO.WriteRope[Rope.Cat["Could not find imported design called '", tilesName, "'.\n"]];
GOTO abort;
};
context.tiles ← import.importee;
};
};
};
cellName ← TerminalIO.RequestRope["What do you want to call the resulting cell? "];
--
Process.SetPriority[Process.priorityBackground];
module ← generatorProc[context];
--
IF module = NIL THEN BEGIN
TerminalIO.WriteRope["A NIL module was produced by the generator.\n"];
GOTO abort;
END;
{
-- did we get a module back?
err: BOOLFALSE;
mod ← CheckValid[module ! Parquet.Error => {err ← TRUE; CONTINUE}];
IF err THEN BEGIN
TerminalIO.WriteRope["An invalid module was produced by the generator!\nMaybe it returned something that was converted to a tile?\n"];
GOTO abort;
END;
};
IF mod.topCell = NIL THEN BEGIN
TerminalIO.WriteRope["A garbaged module was returned by the generator!\n"];
GOTO abort;
END;
TerminalIO.WriteRope["Checking module . . . "];
errs ← CheckModule[module];
IF errs > 0 THEN BEGIN
TerminalIO.WriteInt[errs];
TerminalIO.WriteRope[" ERRORS were found in the generated module, suspect areas are indicated by highlighting.\n"]
END
ELSE
TerminalIO.WriteRope["looks OK to me.\n"];
TerminalIO.WriteRope["Creating ChipNDale cell '"];
TerminalIO.WriteRope[cellName];
TerminalIO.WriteRope["' ..."];
{
ob: CD.ObPtr;
ob ← ModuleIntoCell[module: module, name: cellName, applicationsPerScreenDot: 100];
IF ob = NIL THEN ERROR;
CDOps.AddAnObject[context.eventualOwner, ob, intoPos];
};
RETURN[TRUE];
EXITS
abort => {
TerminalIO.WriteRope["Parquet exiting, no module was generated.\n"];
RETURN[FALSE];
};
END;
GetWorkingDirectory: PROC [design: CD.Design] RETURNS [Rope.ROPE] = BEGIN
wDir: Rope.ROPECDIO.GetWorkingDirectory[design];
IF Rope.IsEmpty[wDir] THEN wDir ← FileNames.CurrentWorkingDirectory[];
RETURN[wDir];
END;
RunTilerDirectly: Commander.CommandProc = BEGIN   
fromFile: BOOL;
tilesName, designName: Rope.ROPENIL;
context: Context ← NEW[ContextRec];
-- load in the tiles
context.workingDirectoryToUse ← FileNames.CurrentWorkingDirectory[];
tilesName ← TerminalIO.RequestRope[Rope.Cat["Enter name of file containg the tiles (", context.workingDirectoryToUse, ") : "]];
tilesName ← FS.ExpandName[tilesName, context.workingDirectoryToUse].fullFName;
context.tiles ← CDIO.ReadDesign[tilesName];
CDIO.SetWorkingDirectory[context.tiles, context.workingDirectoryToUse];
IF context.tiles = NIL THEN {
TerminalIO.WriteRope["Could not load the tiles.\n"];
RETURN[];
}
ELSE
TerminalIO.WriteRope["Tiles loaded.\n"];
-- create design for output
designName ← TerminalIO.RequestRope[Rope.Cat["Enter name for output file (", context.workingDirectoryToUse, ") : "]];
context.eventualOwner ← CDOps.CreateDesign[context.tiles.technology];
CDIO.SetWorkingDirectory[context.eventualOwner, context.workingDirectoryToUse];
-- import the tiles
IF ~CDImports.DoImport[context.eventualOwner, context.tiles, $true] THEN {
TerminalIO.WriteRope["Could not import the tile set!\n"];
RETURN[];
};
-- go for it
fromFile ← TerminalIO.UserSaysYes["From file?", "Do you want to run the module generator from a file (alternate way is to run interactively)?\n", TRUE];
IF ProduceModule[context, [0, 0], fromFile] THEN {
TerminalIO.WriteRope["\nWritting ChipNDale file ...."];
IF ~CDIO.WriteDesign[context.eventualOwner, designName] THEN
TerminalIO.WriteRope["\nOOPS!!! Could not write the ChipNDale file, at least I tried.\n"]
ELSE
TerminalIO.WriteRope["\nDone.\n"];
};
END;
RunTiler: PROC [comm: CDSequencer.Command] = BEGIN   
fromFile: BOOL ← TerminalIO.UserSaysYes["From file?", "Do you want to run a module generator from a file (alternative is to run interactively)?\n", TRUE];
context: Context ← NEW[ContextRec];
context.workingDirectoryToUse ← GetWorkingDirectory[comm.design];
context.eventualOwner ← comm.design;
[] ← ProduceModule[context, comm.pos, fromFile];
END;
RunTilerFromFile: PROC [comm: CDSequencer.Command] = BEGIN   
context: Context ← NEW[ContextRec];
context.workingDirectoryToUse ← GetWorkingDirectory[comm.design];
context.eventualOwner ← comm.design;
[] ← ProduceModule[context, comm.pos, TRUE];
END;
RunTilerWithoutFile: PROC [comm: CDSequencer.Command] = BEGIN   
context: Context ← NEW[ContextRec];
context.workingDirectoryToUse ← GetWorkingDirectory[comm.design];
context.eventualOwner ← comm.design;
[] ← ProduceModule[context, comm.pos, FALSE];
END;
NoOp: Commander.CommandProc = BEGIN   
END;
Init: PROC[] = BEGIN
tilerMenu: REF ← CDMenus.GetMenu[$ModuleMenu];
generatorTable ← SymTab.Create[case: FALSE];
IF tilerMenu=NIL THEN
tilerMenu ← CDMenus.CreateMenu["Module Generator Menu", $ModuleMenu];
CDMenus.ImplementMenuCommand[$ModuleMenu, tilerMenu];
CDSequencer.ImplementCommand[$RunTiler, RunTiler];
CDSequencer.ImplementCommand[$RunTilerFromFile, RunTilerFromFile];
CDSequencer.ImplementCommand[$RunTilerWithoutFile, RunTilerWithoutFile];
CDMenus.CreateEntry[menu: $ModuleMenu, entry: "Run module generator interactively", key: $RunTilerWithoutFile];
CDMenus.CreateEntry[menu: $ModuleMenu, entry: "Run module generator from file", key: $RunTilerWithoutFile];
END;
-- Main body
Init[];
-- register a command.
Commander.Register[key: "GenerateModule", proc: RunTilerDirectly, doc: "Run a module generator"];
-- register a command so that we won't get ".load file failed to register command"
Commander.Register[key: "Parquet", proc: NoOp, doc: "Does nothing"];
END.