RoseRecordImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Barth, September 5, 1985 6:37:22 pm PDT
Spreitzer, November 18, 1985 10:36:53 pm PST
DIRECTORY Basics, BitTwiddling, Convert, CoreOps, IO, PrincOpsUtils, Rope, RoseBehavior, RoseWireClasses, RoseWireFormats, RoseWireTypes, RoseWireTypeUse, RoseWiring, VFonts;
RoseRecordImpl: CEDAR PROGRAM
IMPORTS BitTwiddling, CoreOps, IO, Rope, RoseWireFormats, RoseWireTypeUse, RoseWireTypes, RoseWiring
EXPORTS RoseWireClasses, RoseWireTypes =
BEGIN OPEN CO: CoreOps, RoseWireTypes;
SwitchVal: TYPE = RoseBehavior.SwitchVal;
Level: TYPE = RoseBehavior.Level;
RecordClass: TYPE = REF RecordClassPrivate;
RecordClassPrivate: TYPE = RECORD [
name: ROPE,
bitSize, wordSize: NAT,
repAux: Mesa ← [],
fields: SEQUENCE length: NAT OF RecordClassField
];
RecordClassField: TYPE = RECORD [
name: ROPE,
rwc: RoseWireClass,
bitOffset, bitCount: NAT
];
RecordType: TYPE = REF RecordTypePrivate;
RecordTypePrivate: TYPE = RECORD [
rwt: RoseWireType,
fields: SEQUENCE length: NAT OF RecordTypeField
];
RecordTypeField: TYPE = RECORD [
rwt: RoseWireType
];
GetRecord: PUBLIC PROC [prototype: Wire, flavor: WireFlavor] RETURNS [rwc: RoseWireClass] = {
name: ROPE = RoseWiring.WireName[prototype];
rc: RecordClass ← NEW [RecordClassPrivate[prototype.elements.size]];
rwtUser: RoseWireTypeUse.RoseWireTypeUser = RoseWireTypeUse.CreateUser[];
bitOffset: NAT ← 0;
afterPrev: NAT ← 0;
ComputeOffset: PROC [index, bitCount: NAT] = {
w0: NAT ← bitOffset / Basics.bitsPerWord;
w1: NAT ← (bitOffset + bitCount - 1) / Basics.bitsPerWord;
om: NAT ← bitOffset MOD Basics.bitsPerWord;
IF bitCount > Basics.bitsPerWord AND bitCount MOD Basics.bitsPerWord # 0 THEN ERROR;
IF w1 > w0 AND om # 0 THEN {
delta: NAT ← Basics.bitsPerWord - om;
bitOffset ← bitOffset + delta;
IF index > 0 THEN rc.fields[index - 1].bitOffset ← rc.fields[index - 1].bitOffset + delta;
};
};
def: IO.STREAMIO.ROS[];
firstDefdField: BOOLTRUE;
addressContaining: BOOLFALSE;
AddField: PROC [varFmt, typeFmt: ROPE, first, last: INT, v1, v2: IO.Value ← [null[]] ] = {
firstRem: INT = first MOD Basics.bitsPerWord;
align: ROPE = IO.PutFR[
"(%g:%g..%g)",
[integer[first/Basics.bitsPerWord]],
[integer[firstRem]],
[integer[last - first + firstRem]]
];
IF firstDefdField THEN firstDefdField ← FALSE ELSE def.PutRope[","];
def.PutRope["\n\t"];
def.PutF[varFmt.Cat[align, typeFmt], v1, v2];
};
fillCount: NAT ← 0;
moduleRefs: ARRAY RoseWireTypeUse.ModuleRefType OF LOR;
bitBucket: ROPE;
IF StructureOfWire[prototype] # record THEN ERROR;
rc.name ← name.Cat[WireFlavorName[flavor]];
def.PutF["%g: TYPE = MACHINE DEPENDENT RECORD [", [rope[rc.name]]];
FOR i: NAT IN [0 .. rc.length) DO
ew: Wire = prototype.elements[i];
ewc: RoseWireClass = RoseWiring.GetWiring[ew, flavor];
bitCount: NAT = ewc.super.Bits[ewc];
IF bitCount < 1 THEN ERROR;
ComputeOffset[i, bitCount];
IF CO.GetWireName[ew].Length[] = 0 THEN ERROR;
rc.fields[i] ← [
name: CO.GetWireName[ew],
rwc: ewc,
bitOffset: bitOffset,
bitCount: bitCount
];
addressContaining ← addressContaining OR ewc.dereference OR ewc.addressContaining;
bitOffset ← bitOffset + bitCount;
ENDLOOP;
IF bitOffset > Basics.bitsPerWord AND bitOffset MOD Basics.bitsPerWord # 0 THEN {
delta: NAT ← Basics.bitsPerWord - (bitOffset MOD Basics.bitsPerWord);
bitOffset ← bitOffset + delta;
rc.fields[rc.length-1].bitOffset ← rc.fields[rc.length-1].bitOffset + delta;
};
rc.bitSize ← bitOffset;
rc.wordSize ← (bitOffset + Basics.bitsPerWord - 1)/Basics.bitsPerWord;
FOR i: NAT IN [0 .. rc.length) DO
bitOffset: NAT = rc.fields[i].bitOffset;
swc: RoseWireClass = rc.fields[i].rwc;
sm: Mesa = swc.super.MesaRepresentation[swc];
rwtUser.NoteMesa[sm];
IF afterPrev # bitOffset THEN AddField[
"fill%g", ": [0 .. %g]",
afterPrev,
bitOffset-1,
[integer[fillCount ← fillCount + 1]],
[cardinal[BitTwiddling.oneLessThanTwoToThe[bitOffset-afterPrev]]]
];
afterPrev ← bitOffset + rc.fields[i].bitCount;
AddField[
"%g", ": %g",
bitOffset,
afterPrev-1,
[rope[rc.fields[i].name]],
[rope[sm.mesa]]
];
ENDLOOP;
def.PutRope["]"];
[bitBucket, moduleRefs] ← rwtUser.DestroyUser[];
IF bitBucket.Length[] # 0 THEN ERROR;
rc.repAux.directory ← moduleRefs[Directory];
rc.repAux.imports ← moduleRefs[Import];
IF moduleRefs[Export] # NIL OR moduleRefs[Open] # NIL THEN ERROR;
rc.repAux.mesa ← def.RopeFromROS[];
rwc ← NEW[RoseWireClassRec ← [
structure: record,
dereference: FALSE,
addressContaining: addressContaining,
length: rc.length,
classData: rc,
super: recordSuperClasses[flavor]]];
};
recordSuperClasses: ARRAY WireFlavor OF RoseWireSuperClass ← ALL[NIL];
RecordGetType: PROC [rwc: RoseWireClass, wire: Wire] RETURNS [rwt: RoseWireType] = {
rc: RecordClass = NARROW[rwc.classData];
rt: RecordType = NEW [RecordTypePrivate[wire.elements.size]];
IF StructureOfWire[wire] # record THEN ERROR;
IF rt.length # rc.length THEN ERROR;
FOR i: NAT IN [0 .. rt.length) DO
ew: Wire = wire.elements[i];
ewc: RoseWireClass = rc.fields[i].rwc;
rt.fields[i] ← [
rwt: ewc.super.GetType[ewc, ew]
];
ENDLOOP;
rwt ← NEW[RoseWireTypeRec ← [
class: rwc,
typeData: rt,
length: rt.length,
other: NIL]];
};
RecordListFormats: PROC [rwt: RoseWireType] RETURNS [lor: LOR] = {
lor ← LIST["idiosyncratic", "2", "4", "8", "16"];
};
RecordGetFormat: PROC [rwt: RoseWireType, formatName: ROPE] RETURNS [format: Format] = {
format ← SELECT TRUE FROM
formatName.Equal["2"] => RoseWireFormats.constructNumericRecord[1],
formatName.Equal["4"] => RoseWireFormats.constructNumericRecord[2],
formatName.Equal["8"] => RoseWireFormats.constructNumericRecord[3],
formatName.Equal["16"], formatName=NIL => RoseWireFormats.constructNumericRecord[4],
formatName.Equal["idiosyncratic"] => RoseWireFormats.constructIdiosyncraticRecord,
ENDCASE => ERROR;
};
RecordSelectorOffset: PROC [rwt: RoseWireType, sel: Selector] RETURNS [dBits: NAT] = {
rc: RecordClass = NARROW[rwt.class.classData];
WITH sel SELECT FROM
whole => RETURN [0];
field => RETURN [rc.fields[index].bitOffset];
subscript => ERROR
ENDCASE => ERROR;
};
RecordFieldName: PROC [rwc: RoseWireClass, index: INT] RETURNS [ROPE] = {
rc: RecordClass = NARROW[rwc.classData];
RETURN [rc.fields[index].name];
};
RecordSubType: PROC [rwt: RoseWireType, sel: Selector] RETURNS [RoseWireType] = {
rt: RecordType = NARROW[rwt.typeData];
WITH sel SELECT FROM
whole => RETURN [rwt];
field => RETURN [rt.fields[index].rwt];
subscript => ERROR
ENDCASE => ERROR;
};
RecordSubClass: PROC [rwc: RoseWireClass, sel: Selector] RETURNS [RoseWireClass] = {
rc: RecordClass = NARROW[rwc.classData];
WITH sel SELECT FROM
whole => RETURN [rwc];
field => RETURN [rc.fields[index].rwc];
subscript => ERROR
ENDCASE => ERROR;
};
RecordBits: PROC [rwc: RoseWireClass] RETURNS [n: INT] = {
rc: RecordClass = NARROW[rwc.classData];
n ← rc.bitSize;
};
RecordMesaRepresentation: PROC [rwc: RoseWireClass] RETURNS [mesa: Mesa] = {
rc: RecordClass = NARROW[rwc.classData];
mesa ← [mesa: rc.name];
};
RecordMesaRepAux: PROC [rwc: RoseWireClass] RETURNS [mesa: Mesa] = {
rc: RecordClass = NARROW[rwc.classData];
mesa ← rc.repAux;
};
RecordInitialize: PROC [rwt: RoseWireType, p: Ptr, steady: BOOL] = {
rc: RecordClass = NARROW[rwt.class.classData];
rt: RecordType = NARROW[rwt.typeData];
FOR i: NAT IN [0 .. rc.length) DO
rt.fields[i].rwt.class.super.Initialize[
rt.fields[i].rwt,
BitTwiddling.OffsetPtr[p, rc.fields[i].bitOffset],
steady
];
ENDLOOP;
steady ← steady;
};
RecordTransduce: PROC [fromS: Strength, fromT, toT: RoseWireType, fromP, toP: Ptr] = {
rc: RecordClass = NARROW[fromT.class.classData];
rt: RecordType = NARROW[fromT.typeData];
IF fromT.class.structure # record THEN ERROR;
IF toT.class.structure # record THEN ERROR;
IF fromT.length # toT.length THEN ERROR;
IF toT.class.dereference THEN toP ← BitTwiddling.DeReferencePtr[toP];
FOR i: NAT IN [0 .. rc.length) DO
subFrom: Ptr = BitTwiddling.OffsetPtr[fromP, rc.fields[i].bitOffset];
sel: Selector = [field[i]];
subTo: Ptr = BitTwiddling.OffsetPtr[toP, toT.class.super.SelectorOffset[toT, sel]];
rt.fields[i].rwt.class.super.Transduce[
fromS: fromS,
fromT: rt.fields[i].rwt,
toT: toT.class.super.SubType[toT, sel],
fromP: subFrom,
toP: subTo];
toT ← toT;
ENDLOOP;
toT ← toT;
};
RecordInitQ: PROC [rwt: RoseWireType, p: Ptr, cap: Strength] = TRUSTED {
rc: RecordClass = NARROW[rwt.class.classData];
rt: RecordType = NARROW[rwt.typeData];
FOR i: NAT IN [0 .. rc.length) DO
subType: RoseWireType = rt.fields[i].rwt;
subType.class.super.InitQ[
subType,
BitTwiddling.OffsetPtr[p, rc.fields[i].bitOffset],
cap];
cap ← cap;
ENDLOOP;
cap ← cap;
};
RecordInitUD: PROC [rwt: RoseWireType, p: Ptr, cap: Strength] RETURNS [isInput: BOOL] = TRUSTED {
rc: RecordClass = NARROW[rwt.class.classData];
rt: RecordType = NARROW[rwt.typeData];
isInput ← TRUE;
FOR i: NAT IN [0 .. rc.length) DO
subType: RoseWireType = rt.fields[i].rwt;
subInput: BOOL ← subType.class.super.InitUD[
subType,
BitTwiddling.OffsetPtr[p, rc.fields[i].bitOffset],
cap];
isInput ← isInput AND subInput;
ENDLOOP;
cap ← cap;
};
RecordComputeLevel: PROC [rwt: RoseWireType, p: Ptr, xPhobic: BOOL] RETURNS [delay: BOOL] = TRUSTED {
rc: RecordClass = NARROW[rwt.class.classData];
rt: RecordType = NARROW[rwt.typeData];
delay ← FALSE;
FOR i: NAT IN [0 .. rc.length) DO
subType: RoseWireType = rt.fields[i].rwt;
subDelay: BOOL ← subType.class.super.ComputeLevel[
subType,
BitTwiddling.OffsetPtr[p, rc.fields[i].bitOffset],
xPhobic];
delay ← delay OR subDelay;
ENDLOOP;
xPhobic ← xPhobic;
};
WireValBreak: PUBLIC PROC [char: CHAR] RETURNS [IO.CharClass] --IO.BreakProc-- = {
RETURN [SELECT char FROM
IN [IO.NUL .. IO.SP] => sepr,
',, ':, '[, '] => break,
ENDCASE => other
];
};
Start: PROC = {
FOR wf: WireFlavor IN WireFlavor DO
recordSuperClasses[wf] ← NEW[RoseWireSuperClassRec ← [
GetType: RecordGetType,
ListFormats: RecordListFormats,
GetFormat: RecordGetFormat,
SelectorOffset: RecordSelectorOffset,
FieldName: RecordFieldName,
SubType: RecordSubType,
SubClass: RecordSubClass,
Bits: RecordBits,
MesaRepresentation: RecordMesaRepresentation,
MesaRepAux: RecordMesaRepAux,
flavor: wf,
Initialize: RecordInitialize,
Transduce: RecordTransduce,
InitQ: RecordInitQ,
InitUD: RecordInitUD,
ComputeLevel: RecordComputeLevel
]];
ENDLOOP;
};
Start[];
END.