<> <> <> <> DIRECTORY CD, CDAtomicObjects, CDBasics, CDCallSpecific, CDIO, CDIOExtras, CDLRUCache, CDOrient, RefTab, Rope, RuntimeError, TokenIO; CDAtomicObjectsImpl: CEDAR MONITOR IMPORTS CD, CDBasics, CDCallSpecific, CDIO, CDIOExtras, CDLRUCache, CDOrient, RefTab, RuntimeError, TokenIO EXPORTS CDAtomicObjects SHARES CD = --want access technology of ObjectClass BEGIN <<--This module helps the implementation of a wide class of atomic ChipNDale>> <<--objects, which do not have children and are shared between designs. Despite>> <<--its name this are not the only atomic object classes. >> DrawRec: TYPE = CDAtomicObjects.DrawRec; <<--RECORD [r: CD.Rect, lev: CD.Layer _ CD.highLightError];>> DrawList: TYPE = CDAtomicObjects.DrawList; <<--LIST OF DrawRec;>> AtomicObsPtr: TYPE = CDAtomicObjects.AtomicObsPtr; <<--REF AtomicObsRec;>> AtomicObsRec: TYPE = CDAtomicObjects.AtomicObsRec; <<--RECORD [ >> <<-- rList: DrawList_NIL, --do not change directly>> <<-- ir: CD.Rect, --do not change directly>> <<-- ];>> <<>> FillObjectProc: TYPE = CDAtomicObjects.FillObjectProc; <<--PROC [ob: CD.Object] RETURNS [mustFail: BOOL _ FALSE];>> <<--read (and even rewrite) size, layer>> <<--calls IncorporateRect>> <<--do not read or write ir>> <<--rList will be initialized to NIL>> ------------ classTable: RefTab.Ref = RefTab.Create[41]; ClassEntry: TYPE = RECORD[ tech: CD.Technology, fillProc: FillObjectProc, class: REF CD.ObjectClass_NIL ]; GetClassEntry: PROC [classKey: ATOM, tech: CD.Technology] RETURNS [ce: REF ClassEntry_NIL] = INLINE BEGIN class: REF CD.ObjectClass = CD.FetchObjectClass[classKey, tech]; IF class#NIL THEN ce _ NARROW[ classTable.Fetch[class].val ] END; ------------ cache1: CDLRUCache.LRUCache = CDLRUCache.Create[size: 37, aequivalenceProc: AequivalenceAO]; cache2: CDLRUCache.LRUCache = CDLRUCache.Create[size: 37, aequivalenceProc: AequivalenceAO]; cache3: CDLRUCache.LRUCache = CDLRUCache.Create[size: 37, aequivalenceProc: AequivalenceAO]; myRectPtr: CD.RectPtr = NEW[CD.RectRep]; AequivalenceAO: PROC [mySpecific, other: REF ANY] RETURNS [BOOL] = { <<--Insider info: mySpecific is already in the cache; other is the one to be inserted>> RETURN [~ISTYPE[mySpecific, CD.RectPtr]] }; ------------ CreateAtomicOb: PUBLIC PROC [classKey: ATOM, size: CD.Position, tech: CD.Technology, lev: CD.Layer_CD.combined] RETURNS [ob: CD.Object_NIL] = <<--NIL if not done>> BEGIN ENABLE UNWIND => NULL; ce: REF ClassEntry = GetClassEntry[classKey, tech]; size _ CDBasics.MaxPoint[size, [1, 1]]; IF ce#NIL THEN { cache: CDLRUCache.LRUCache _ SELECT size.x+size.y FROM <=30 => cache1, --any minimal size ndiff construct <=60 => cache2, --any minimal size pdiff construct ENDCASE => cache3; --long crazy stuff aop: AtomicObsPtr = NEW[AtomicObsRec _ [ir: CDBasics.empty]]; ob1: CD.Object _ cache.UnusedOrNew[]; ob1.class _ ce.class; ob1.size _ size; ob1.layer _ lev; ob1.specificRef _ aop; IF ce.fillProc[ob1 ! RuntimeError.UNCAUGHT => GOTO xx].mustFail THEN RETURN [NIL]; ob _ cache.ReplaceByAequivalent[ob1]; <<--as efficiencyhack, the object is now already in the lru cache, inspite>> <<--of not yet beeing checked.>> <<--If object is bad, however, the technology implementing code is bad, and therefore>> <<--we do not really feel responsible for the design...>> IF ob=ob1 THEN { --new entry IF ~CDBasics.Inside[aop.ir, CDBasics.RectAt[[0, 0], ob.size]] OR CDBasics.empty=aop.ir OR aop.rList=NIL THEN GOTO xx; <<--now check if we should change the objectprocs to be more general>> IF aop.ir#CDBasics.RectAt[[0, 0], ob.size] THEN { IF aop.ir.x1<0 OR aop.ir.y1<0 OR aop.ir.x2>ob.size.x OR aop.ir.y2>ob.size.y THEN GOTO xx; IF ce.class.showMeSelected=XShowSelectedAO THEN { class: REF CD.ObjectClass = ob.class; class.showMeSelected _ ShowSelectedAO; } }; }; }; EXITS xx => RETURN WITH ERROR CD.Error[other, "Error in technology, implementing creation of atomic object"]; END; RegisterAtomicObClass: PUBLIC PROC [classKey: ATOM, fillProc: FillObjectProc, description: Rope.ROPE_NIL, tech: CD.Technology_NIL] RETURNS [type: REF CD.ObjectClass _ NIL] = <<--drawMe, quickDrawMe are considered variables and should not >> <<--be changed by class implementor.>> BEGIN ce: REF ClassEntry _ NEW[ClassEntry_[ tech: tech, fillProc: fillProc ]]; done: BOOL_TRUE; ce.class _ type _ CD.RegisterObjectClass[classKey, tech ! CD.Error => {done _ FALSE; CONTINUE}]; IF ~done THEN RETURN WITH ERROR CD.Error[doubleRegistration]; done _ RefTab.Insert[classTable, type, ce]; type.drawMe _ type.quickDrawMe _ DrawAO; type.internalRead _ ReadAO; type.internalWrite _ WriteAO; type.interestRect _ InsideAO; type.showMeSelected _ XShowSelectedAO; type.wireTyped _ FALSE; type.description _ description; CDCallSpecific.Register[$Lengthen, type, LengthenAO]; END; Incorporate: PUBLIC PROC [ob: CD.Object, r: CD.Rect, lev: CD.Layer, inside: BOOL _ TRUE] = BEGIN aop: AtomicObsPtr = NARROW[ob.specificRef]; IF inside THEN aop.ir _ CDBasics.Surround[aop.ir, r]; aop.rList _ CONS[[r, lev], aop.rList]; END; -------------- ReadAO: CD.InternalReadProc --PROC [] RETURNS [Object]-- = BEGIN sz: CD.Position _ CDIOExtras.ReadPos[]; code: ATOM = TokenIO.ReadAtom[]; lev: CD.Layer = CDIO.ReadLayer[]; tech: CD.Technology = CDIO.DesignInReadOperation[].technology; ob: CD.Object _ CreateAtomicOb[code, sz, tech, lev]; IF CDIO.VersionKey[]<10 THEN { <<--The old way had the size instead the interest rect in the file>> ob _ CreateAtomicOb[code, [sz.x - (ob.size.x-sz.x), sz.y - (ob.size.y-sz.y)], tech, lev]; }; RETURN [ob] END; WriteAO: CD.InternalWriteProc -- PROC [me: Object] -- = BEGIN CDIOExtras.WritePos[CD.InterestSize[me]]; TokenIO.WriteAtom[me.class.objectType]; CDIO.WriteLayer[me.layer]; END; DrawAO: PROC [inst: CD.Instance, pos: CD.Position, orient: CD.Orientation, pr: CD.DrawRef] = BEGIN FOR class: DrawList _ NARROW[inst.ob.specificRef, AtomicObsPtr].rList, class.rest WHILE class#NIL DO pr.drawRect[ CDOrient.MapRect[ itemInCell: class.first.r, cellSize: inst.ob.size, cellInstOrient: orient, cellInstPos: pos], class.first.lev, pr] ENDLOOP; END; ShowSelectedAO: PROC [inst: CD.Instance, pos: CD.Position, orient: CD.Orientation, pr: CD.DrawRef] = BEGIN aop: AtomicObsPtr = NARROW[inst.ob.specificRef]; pr.drawOutLine[ CDOrient.MapRect[ itemInCell: aop.ir, cellSize: inst.ob.size, cellInstOrient: orient, cellInstPos: pos], pr] END; XShowSelectedAO: PROC [inst: CD.Instance, pos: CD.Position, orient: CD.Orientation, pr: CD.DrawRef] = BEGIN pr.drawOutLine[CDOrient.RectAt[pos, inst.ob.size, orient], pr] END; InsideAO: PROC [ob: CD.Object] RETURNS [CD.Rect] = BEGIN RETURN [NARROW[ob.specificRef, AtomicObsPtr].ir] END; LengthenAO: CDCallSpecific.CallProc = <<--PROC [design: CD.Design, inst: CD.Instance, x: REF] >> <<--RETURNS [done: BOOL_TRUE, removeMe: BOOL_FALSE, include: CD.InstanceList_NIL,>> <<--repaintMe: BOOL_FALSE, repaintInclude: BOOL_FALSE]>> BEGIN ToPosition: PROC [x: REF] RETURNS [class: CD.Position] = <<--y field defaults to lambda, x field defaults to 0>> <<--[0, 0] if not done>> BEGIN IF x=NIL THEN class _ [0, design.technology.lambda] ELSE WITH x SELECT FROM rp: REF CD.Position => class _ rp^; rn: REF CD.Number => class _ [0, rn^]; ENDCASE => class _ [0, 0]; END; <<>> <<--LengthenAO>> amount: CD.Position = ToPosition[x]; IF amount.y=0 AND amount.x=0 THEN done _ FALSE ELSE { sz: CD.Position _ CDBasics.AddPoints[CD.InterestSize[inst.ob], amount]; new: CD.Object _ CreateAtomicOb[size: sz, classKey: inst.ob.class.objectType, lev: inst.ob.layer, tech: inst.ob.class.technology]; done _ new#NIL AND new#inst.ob AND new.size#inst.ob.size; IF done THEN { inst.ob _ new; repaintMe _ TRUE; } }; END; END.