IOBDesign.mesa
Copyright © 1986 by Xerox Corporation. All rights reserved.
Jean-Marc Frailong, August 31, 1987 8:50:36 pm PDT
Description of some wire icons in IOBDesign. Most of them could/should be replaced by schematics now that wire icons are correctly supported in Sisyph.
Command to switch wire sizes between regular & bus-size
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
Design Constants
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
Structured buses
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] ~ {
Creates an interleaved wire icon: even, odd, interleaved. Each side is b bits, full bus is 2b bits.
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];
};
DBus slave block
DBusSlave: PROC [cx: Sisyph.Context, dummy: BOOL] RETURNS [ct: Core.CellType] ~ {
Return the real thing if dummy=FALSE, a version with hardwired constant registers if dummy=TRUE
ct ← Sisyph.ES[IF dummy THEN "DummyDBusSlave.sch" ELSE "DBusSlave.sch", cx];
};
Sanity check of SC block(s)
CheckSCBlock: PROC [comm: CDSequencer.Command] ~ {
Notify of all public atomics that do not have geometry
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];
};
Pin definition
name: TYPE ~ type declaration;
DefinePins: PROC [Args] RETURNS [Results] ~ {
Pins are described in LeftToRight, BottomToTop order as required by SC.
Internal: PROC [internal: Rope.ROPE] ~ {
Register wire on current side of SC block.
TBD
};
Pad: PROC [pad: Rope.ROPE] ~ {
Register wire on current side of chip.
TBD
};
External: PROC [internal: Rope.ROPE, pad: Rope.ROPE] ~ {
Wire is named internal on the SC block and pad on the chip boundary. The wire is an atomic input or output..
Pad[pad];
Internal[internal];
};
BusInternal: PROC [internal: Rope.ROPE, from: NAT, for: NAT] ~ {
Wire is named internal on the SC block, but does not propagate to the side of the chip. The wire is a bus, of which bits [from..from+for) are used, as for extractors. Each of its atomic wires are input or output. The MSB has the lowest position.
FOR i: NAT IN [from..from+for) DO
suffix: ROPE = IO.PutFR["[%g]", IO.int[i]];
Internal[internal.Concat[suffix]];
ENDLOOP;
};
BusExternal: PROC [internal: Rope.ROPE, pad: Rope.ROPE, from: NAT, for: NAT] ~ {
Wire is named internal on the SC block and pad on the chip boundary. The wire is a bus, of which bits [from..from+for) are used, as for extractors. Each of its atomic wires are input or output. The MSB has the lowest position.
FOR i: NAT IN [from..from+for) DO
suffix: ROPE = IO.PutFR["[%g]", IO.int[i]];
External[internal.Concat[suffix], pad.Concat[suffix]];
ENDLOOP;
};
IOInternal: PROC [input, output: Rope.ROPE] ~ {
Wire has an input and an output wires on the SC block, but does not propagate to the side of the chip. The input has the lowest coordinate on the SC block.
Internal[input];
Internal[output];
ENDLOOP;
};
IOExternal: PROC [input, output: Rope.ROPE, pad: Rope.ROPE] ~ {
Wire has an input and an output wires on the SC block and pad on the chip boundary. The input has the lowest coordinate on the SC block.
Pad[pad];
Internal[input];
Internal[output];
ENDLOOP;
};
IOBusInternal: PROC [input, output: Rope.ROPE, from: NAT, for: NAT] ~ {
Wire is an IO bus that does not propagate to the chip boundary. Components are extracted according to from and for. Order is in[0], out[0], in[1], out[1], ...
FOR i: NAT IN [from..from+for) DO
suffix: ROPE = IO.PutFR["[%g]", IO.int[i]];
IOInternal[input.Concat[suffix], output.Concat[suffix]];
ENDLOOP;
};
IOBusExternal: PROC [input, output: Rope.ROPE, pad: Rope.ROPE, from: NAT, for: NAT] ~ {
Wire is an IO bus that propagates to the chip boundary. Components are extracted according to from and for. Order is in[0], out[0], in[1], out[1], ...
FOR i: NAT IN [from..from+for) DO
suffix: ROPE = IO.PutFR["[%g]", IO.int[i]];
IOExternal[input.Concat[suffix], output.Concat[suffix], pad.Concat[suffix]];
ENDLOOP;
};
LeftSide: PROC ~ {
Define pins on left side
External["nHeaderIn", ""];
External["nGrant", ""];
External["ITIOBus", ""];
External["INT", ""];
External["MBReq", ""];
External["MBAck", ""];
External["PCLK", ""];
BusExternal["iDBus", "", 0, 7];
External["iDSelect", ""];
BusInternal["ExtraMapIn", 0, 6];
Internal["WExtra"];
BusInternal["LargeMapIn", 0, 14];
Internal["WLarge"];
BusInternal["SmallMapIn", 0, 22];
Internal["WSmall"];
BusInternal["MapOut", 0, 22];
BusInternal["MapAddr", 0, 4];
IOBusExternal["PBusIn", "PBusOut","" , 0, 32];
Internal["DrvPBus"];
BusInternal["FifoWAddr", 0, 4];
Internal["FifoWPulse"];
IOBusInternal["RqstIn", "RqstOut", 0, 81];
BusInternal["FifoRAddr", 0, 4];
External["iPReject", ""];
External["iPFault", ""];
BusExternal["iPCmd", "", 0, 7];
External["iPhA", ""];
External["iPhB", ""];
External["nRequest[0]", ""];
External["nSStopOut", ""];
External["nParityOut", ""];
};
RightSide: PROC ~ {
Define pins on left side
External["nParityIn", ""];
External["nSStopIn", ""];
External["nGLength", ""];
IOExternal["IOBAddrIn[31]", "nDEN", ""];
IOExternal["IOBAddrIn[30]", "DTnR", ""];
IOExternal["IOBAddrIn[29]", "MnINTA", ""];
BusExternal["IOBAddrIn", "", 24, 5];
IOBusExternal["IOBAddrIn", "IOBAddrOut", "", 0, 24];
IOExternal["nBHEIn", "nBHEOut", ""];
Internal["EnMOut"];
Internal["EnSOut"];
Internal["EnDOut"];
IOBusExternal["IOBDataIn", "IOBDataOut", "", 0, 16];
External["SnIOCS", ""];
External["SnMemCS", ""];
IOExternal["IOCheck", "nITFault", ""];
IOExternal["SnRD", "MnRD", ""];
IOExternal["SnWR", "MnWR", ""];
IOExternal["SnRDXnIOR", "MnIOR", ""];
IOExternal["SnWRXnIOW", "MnIOW", ""];
External["HReset", ""];
IOExternal["MnReady", "SnReady", ""];
External["nRequest[1]", ""];
External["nHeaderOut", ""];
External["CK", ""];
};
TopSide: PROC ~ {
Define pins on top side
IOBusExternal["nDataIn", "nDataOut", "", 0, 32];
};
BottomSide: PROC ~ {
Define pins on bottom side
IOBusExternal["nDataIn", "nDataOut", "", 32, 64];
};
};
Big wires versus small wires
IsWire: PROC [inst: CD.Instance] RETURNS [BOOL] ~ {
Return TRUE if the object of the instance is a schematics wire
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𡤀] = {
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] ~ {
The command to enlarge/shrink all selected wires
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]];
};
Initialization
CDSequencer.ImplementCommand[$SwitchWireSize, SwitchWireSizeCommand];
CDSequencer.ImplementCommand[$CheckSCBlock, CheckSCBlock];
END.