<> <> <> <<>> <> <> <<>> DIRECTORY CD USING [commentLayer, Instance, InstanceList, InterestSize, Number, Object, Position, Rect], CDBasics USING [AddPoints, Extend, SubPoints, Surround], CDInstances USING [InstRectI, InstRectO], CDLayers USING [LayerWidth], CDOps USING [InstList, Redraw], CDRects USING [CreateRect, IsBareRect], CDSequencer USING [Command, ImplementCommand], Core USING [CellType, Wire, Wires], CoreCreate USING [Range, Seq], CoreGeometry USING [Decoration, HasPins], CoreOps USING [GetFullWireNames, SetShortWireName, VisitRootAtomics], IO USING [int, rope], Rope USING [ROPE], Sinix USING [Mode], SinixOps USING [SelectedCellType], Sisyph USING [Context, ES, mode], TerminalIO USING [PutF, PutRope]; IOBDesign: CEDAR PROGRAM IMPORTS CD, CDBasics, CDInstances, CDLayers, CDOps, CDRects, CDSequencer, CoreCreate, CoreGeometry, CoreOps, IO, SinixOps, Sisyph, TerminalIO ~ BEGIN <> CacheType: INT _ 001H; -- Constant defined in DynaBus protocol, Appendix B IOWRQ: INT _ 012H; -- Constant defined by the DynaBus protocol BIOWRQ: INT _ 014H; -- Constant defined by the DynaBus protocol ByteType: INT _ 02H; -- Constant defined by the IOBridge specs WordType: INT _ 03H; -- Constant defined by the IOBridge specs LongType: INT _ 04H; -- Constant defined by the IOBridge specs IOType: INT _ 02H; -- Constant defined by the IOBridge specs <> Fields: TYPE ~ LIST OF Field; Field: TYPE ~ REF FieldRep; FieldRep: TYPE ~ RECORD [name: Rope.ROPE, size: NAT]; -- size 0 means field is atomic wire Fld: PROC [name: Rope.ROPE, size: NAT _ 0] RETURNS [Field] ~ INLINE { RETURN [NEW[FieldRep _ [name, size]]] }; BusStructure: PROC [name: Rope.ROPE, size: NAT, fields: Fields] RETURNS [public: Core.Wires] ~ { bus: Core.Wire _ CoreCreate.Seq[name, size]; base: NAT _ 0; public _ LIST [bus]; WHILE fields#NIL DO f : Field = fields.first; IF f.size=0 THEN { -- Extraction of an atomic field public _ CONS [CoreOps.SetShortWireName[bus[base], f.name], public]; base _ base+1; } ELSE { -- Extraction of a regular field public _ CONS [CoreCreate.Range[bus, base, f.size, f.name], public]; base _ base+f.size; }; fields _ fields.rest; ENDLOOP; IF size#base THEN ERROR; -- the sum of field sizes is not equal to the bus size! }; Request: PROC [] RETURNS [public: Core.Wires] ~ { public _ BusStructure[name: "Request", size: 81, fields: LIST[ Fld["Cmd", 5], Fld["Mode"], Fld["IORange"], Fld["DeviceID", 10], Fld["Address", 32], Fld["Data", 32]]]; }; RequestH: PROC [] RETURNS [public: Core.Wires] ~ { public _ BusStructure[name: "RequestH", size: 49, fields: LIST[ Fld["Cmd", 5], Fld["Mode"], Fld["IORange"], Fld["DeviceID", 10], Fld["Address", 32]]]; }; Header: PROC [] RETURNS [public: Core.Wires] ~ { public _ BusStructure[name: "Header", size: 64, fields: LIST[ Fld["Cmd", 5], Fld["ModeError"], Fld["Shared"], Fld["DeviceID", 10], Fld["Address", 47]]]; }; IOAddress: PROC [] RETURNS [public: Core.Wires] ~ { public _ BusStructure[name: "IOA", size: 47, fields: LIST[ Fld["ZA", 15], Fld["Addr", 32]]]; }; IOLargeAddr: PROC [] RETURNS [public: Core.Wires] ~ { public _ BusStructure[name: "IOLarge", size: 32, fields: LIST[ Fld["DevT", 4], Fld["DevN", 4], Fld["DevSA", 24]]]; }; IOMediumAddr: PROC [] RETURNS [public: Core.Wires] ~ { public _ BusStructure[name: "IOMedium", size: 32, fields: LIST[ Fld["DevT", 8], Fld["DevN", 8], Fld["DevSA", 16]]]; }; IOSmallAddr: PROC [] RETURNS [public: Core.Wires] ~ { public _ BusStructure[name: "IOSmall", size: 32, fields: LIST[ Fld["DevT", 12], Fld["DevN", 10], Fld["DevSA", 10]]]; }; Interleave: PROC [b: NAT] RETURNS [public: Core.Wires] ~ { <> even: Core.Wire _ CoreCreate.Seq["Even", b]; odd: Core.Wire _ CoreCreate.Seq["Odd", b]; interleaved: Core.Wire _ CoreCreate.Seq["Interleaved", 2*b]; FOR i: NAT IN [0..b) DO interleaved[2*i] _ even[i]; interleaved[2*i+1] _ odd[i]; ENDLOOP; public _ LIST [even, odd, interleaved]; }; <> DBusSlave: PROC [cx: Sisyph.Context, dummy: BOOL] RETURNS [ct: Core.CellType] ~ { <> ct _ Sisyph.ES[IF dummy THEN "DummyDBusSlave.sch" ELSE "DBusSlave.sch", cx]; }; <> CheckSCBlock: PROC [comm: CDSequencer.Command] ~ { <> CheckPins: PROC [wire: Core.Wire] ~ { names: LIST OF Rope.ROPE; IF CoreGeometry.HasPins[decoration, wire] THEN RETURN; names _ CoreOps.GetFullWireNames[ct.public, wire]; IF names=NIL THEN names _ LIST ["-- Unnamed --"]; TerminalIO.PutF["Wire %g", IO.rope[names.first]]; WHILE names.rest#NIL DO names _ names.rest; TerminalIO.PutF[", %g", IO.rope[names.first]]; ENDLOOP; TerminalIO.PutF[" has no pin geometry\n"]; }; root, ct: Core.CellType; mode: Sinix.Mode = Sisyph.mode; decoration: CoreGeometry.Decoration = mode.decoration; [root: root, cell: ct] _ SinixOps.SelectedCellType[comm.design, mode]; IF root=NIL THEN RETURN; CoreOps.VisitRootAtomics[ct.public, CheckPins]; }; <> <<name: TYPE ~ type declaration;>> <> <> <> <> <<TBD>> <<};>> <> <> <<TBD>> <<};>> <> <> <> <> <<};>> <> <> <> <> <> <> <<};>> <> <> <> <> <> <> <<};>> <> <> <> <> <> <<};>> <> <> <> <> <> <> <<};>> <> <> <> <> <> <> <<};>> <> <> <> <> <> <> <<};>> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <<};>> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <<};>> <> <> <> <<};>> <> <> <> <<};>> <<};>> <> IsWire: PROC [inst: CD.Instance] RETURNS [BOOL] ~ { <> RETURN [inst.ob.layer=CD.commentLayer AND CDRects.IsBareRect[inst.ob]] }; <<>> FiddlePos: PROC [inst: CD.Instance, ir: CD.Rect] = { MoreZero: PROC [a, b: INT] RETURNS [INT_0] = { IF a>=0 AND b>=0 THEN RETURN [MIN[a, b]]; IF a<=0 AND b<=0 THEN RETURN [MAX[a, b]]; }; r: CD.Rect _ CDInstances.InstRectI[inst]; inst.trans.off.x _ inst.trans.off.x + MoreZero[ir.x1-r.x1, ir.x2-r.x2]; inst.trans.off.y _ inst.trans.off.y + MoreZero[ir.y1-r.y1, ir.y2-r.y2]; }; SwitchWireSizeCommand: PUBLIC PROC [comm: CDSequencer.Command] ~ { <> shrunk: INT _ 0; enlarged: INT _ 0; smallW: CD.Number = CDLayers.LayerWidth[comm.design, CD.commentLayer]; largeW: CD.Number = 3*smallW; TerminalIO.PutRope["switch size of selected wires\n"]; FOR list: CD.InstanceList _ CDOps.InstList[comm.design], list.rest WHILE list#NIL DO inst: CD.Instance _ list.first; -- instance may be modified ! IF inst.selected AND IsWire[inst] THEN { size: CD.Position = CD.InterestSize[inst.ob]; delta: CD.Number; SELECT MIN [size.x, size.y] FROM smallW => delta _ smallW; largeW => delta _ -smallW; ENDCASE => delta _ 0; IF delta#0 THEN { -- modify the instance goal: CD.Rect = CDBasics.Extend[CDInstances.InstRectI[inst], delta]; oldRect: CD.Rect = CDInstances.InstRectO[inst]; inst.ob _ CDRects.CreateRect[CDBasics.AddPoints[size, [2*delta, 2*delta]], inst.ob.layer]; inst.trans.off _ CDBasics.SubPoints[inst.trans.off, [delta, delta]]; FiddlePos[inst, goal]; -- move instance to fit goal: transf are the plague of CD CDOps.Redraw[comm.design, CDBasics.Surround[oldRect, CDInstances.InstRectO[inst]]]; IF delta>0 THEN enlarged _ enlarged + 1 ELSE shrunk _ shrunk + 1; }; }; ENDLOOP; TerminalIO.PutF["Enlarged %g wire(s), shrunk %g wire(s)\n", IO.int[enlarged], IO.int[shrunk]]; }; <> CDSequencer.ImplementCommand[$SwitchWireSize, SwitchWireSizeCommand]; CDSequencer.ImplementCommand[$CheckSCBlock, CheckSCBlock]; END.