FP.Mesa
created by RoseTranslate 2.8.8 of January 28, 1985 2:26 pm PST from FP.Rose of February 8, 1985 4:49:19 pm PST
created for curry.pa
created at February 8, 1985 4:49:23 pm PST
DIRECTORY
RoseTypes, RoseCreate, IO, Dragon, DragonFP, PrintTV, AMBridge;
FP:
CEDAR
PROGRAM
IMPORTS RoseCreate, IO, Dragon, DragonFP, PrintTV, AMBridge =
Signal Type decls
CSLoad: TYPE = DragonFP.CSLoad;
CSUnload: TYPE = DragonFP.CSUnload;
PBusFaults: TYPE = Dragon.PBusFaults;
RegisterCells:
PROC =
BEGIN
END;
otherss: SymbolTable ← RoseCreate.GetOtherss["FP.pass"];
FPDeviceArgs:
PUBLIC
TYPE =
RECORD [
type: FPDeviceType];
OldFPDevice: TYPE = RECORD [args: FPDeviceArgs, ct: CellType];
oldFPDevice: LIST OF OldFPDevice ← NIL;
FPDevice:
PUBLIC
PROC [args: FPDeviceArgs]
RETURNS [ct: CellType] =
BEGIN
FOR old:
LIST
OF OldFPDevice ← oldFPDevice, old.rest
WHILE old #
NIL
DO
IF old.first.args = args THEN RETURN [old.first.ct]
ENDLOOP;
ct ← RoseCreate.RegisterCellType[name: FPDeviceName[args],
expandProc: NIL,
ioCreator: CreateFPDeviceIO, initializer: InitializeFPDevice,
evals: [EvalSimple: FPDeviceEvalSimple],
tests: LIST[],
ports: CreateFPDevicePorts[args],
driveCreator: CreateFPDeviceDrive,
typeData: NEW [FPDeviceArgs ← args]];
oldFPDevice ← CONS[[args, ct], oldFPDevice];
END;
FPDeviceName:
PROC [args: FPDeviceArgs]
RETURNS [name:
ROPE] = {
to: IO.STREAM ← IO.ROS[]; to.PutRope["FPDevice"];
TRUSTED {PrintTV.Print[tv: AMBridge.TVForReferent[NEW [FPDeviceArgs ← args]], put: to]};
name ← IO.RopeFromROS[to]};
CreateFPDevicePorts: PROC [args: FPDeviceArgs] RETURNS [ports: Ports] = {ports ← RoseCreate.PortsFromFile["FP.FPDevice.rosePorts"]};
FPDeviceIORef: TYPE = REF FPDeviceIORec;
FPDeviceIORec:
TYPE =
MACHINE
DEPENDENT
RECORD [
CSLd3AB(0): CSLoad,
CSUn2AB(1): CSUnload,
EPFaultB(2): PBusFaults,
EPData(3): ARRAY [0..2) OF CARDINAL,
KBus(5): ARRAY [0..2) OF CARDINAL,
PhA(7): BOOLEAN,
PhB(8): BOOLEAN,
InstrCountAB(9): ARRAY [0..2) OF CARDINAL];
FPDeviceDriveRef: TYPE = REF FPDeviceDriveRec;
FPDeviceDriveRec: TYPE = RECORD [tag: DriveTagType, s: PACKED ARRAY FPDevicePort OF DriveLevel];
FPDevicePort:
TYPE =
MACHINE
DEPENDENT {
CSLd3AB, CSUn2AB, EPFaultB, EPData, KBus, PhA, PhB, InstrCountAB};
CreateFPDeviceIO:
PROC [ct: CellType]
RETURNS [ioAsAny:
REF
ANY]
--IOCreator-- = {
ioAsAny ← NEW[FPDeviceIORec];
};
CreateFPDeviceDrive:
PROC [ct: CellType]
RETURNS [driveAsAny:
REF
ANY]
--DriveCreator-- = {
driveAsAny ← NEW[FPDeviceDriveRec];
};
FPDeviceStateRef: TYPE = REF FPDeviceStateRec;
FPDeviceStateRec:
TYPE =
RECORD [
f0, f1, freg: DragonFP.Function,
mode: DragonFP.Mode,
x0, x1: Dragon.HexWord,
aM, aL, bM, bL: Dragon.HexWord,
arM, arL, brM, brL: Dragon.HexWord,
aluCSL1, mulCSL1: DragonFP.CSLoad,
aluCSU1, mulCSU1: DragonFP.CSUnload,
aluCSU2, mulCSU2: DragonFP.CSUnload,
load0, load1: DragonFP.Load,
unload0, unload1: DragonFP.Unload,
aluST0, mulST0: Dragon.PBusFaults,
aluST1, mulST1: Dragon.PBusFaults,
aluDM, mulDM: Dragon.HexWord,
aluDL, mulDL: Dragon.HexWord,
aluZ, mulZ: Dragon.HexWord
];
InitializeFPDevice: Initializer = {
IF leafily
THEN
BEGIN
args: REF FPDeviceArgs ← NARROW [cell.type.typeData];
state: FPDeviceStateRef ← NEW[FPDeviceStateRec];
cell.realCellStuff.state ← state;
END;
};
FPDeviceEvalSimple: CellProc =
BEGIN
args: REF FPDeviceArgs ← NARROW[cell.type.typeData];
newIO: FPDeviceIORef ← NARROW[cell.realCellStuff.newIO];
state: FPDeviceStateRef ←
NARROW[cell.realCellStuff.state];
BEGIN
OPEN newIO, args, state;
IF PhA
THEN {
clocked ← FALSE;
load0 ← LOOPHOLE[BitOps.ECFD[KBus, 32, 16+ 2, 5]];
f0 ← LOOPHOLE[BitOps.ECFD[KBus, 32, 16+ 7, 1]];
unload0 ← LOOPHOLE[BitOps.ECFD[KBus, 32, 16+10, 6]];
x0 ← Dragon.LFD[EPData];
};
IF
NOT PhA
AND
NOT clocked
THEN {
clocked ← TRUE;
cycle ← MAX[cycle-1, -1]; -- off at -1
IF cycle=0 THEN
csU2 ← csU1;
[[aluDM, aluDL], aluST0] ← (
SELECT type
FROM
Alu => DragonFP.ALU [[arM,arL], [brM,brL], freg, mode, aArg, bArg],
Mult => DragonFP.MUL [[arM,arL], [brM,brL], freg, mode, aArg, bArg]);
csU1 ← CSUn2AB;
IF CSUn2AB=unload
THEN
SELECT code
FROM
fpLdSglAUnMsw => {ibus ← dm};
fpLdLswAUnLsw => {ibus ← dl};
fpLdMswAUnMsw => {ibus ← dm};
ENDCASE => Dragon.Assert[FALSE, "Unimplemented unload code"] };
IF CSLd3AB=load
THEN {
SELECT code
FROM
fpLdSglBSt => {brS ← ibus; freg start←TRUE};
fpLdLswB => {brL ← ibus; start←FALSE};
fpLdLswBSt => {brL ← ibus; freg start←TRUE};
fpLdMswB => {brM ← ibus; start←FALSE};
fpLdMswBSt => {brM ← ibus; freg start←TRUE};
fpLdSglAUnMsw => {arS ← ibus; unload←msw; start←FALSE};
fpLdLswAUnLsw => {arL ← ibus; unload←lsw; start←FALSE};
fpLdMswAUnMsw => {arM ← ibus; unload←msw; start←FALSE};
delGamBetAlp => mode ← DragonFP.SetMode[mode, f1];
ENDCASE => Dragon.Assert[FALSE, "Unimplemented load code"] };
aluZ ← IF unload1=msw THEN aluDM ELSE aluDL;
mulZ ← IF unload1=msw THEN mulDM ELSE mulDL;
unload1 ← unload0;
aluST1 ← aluST0;
mulST1 ← mulST0;
IF mulCSL1=load THEN { };
SELECT load1
FROM
none => { };
func => {arM𡤊M; arL𡤊L; brM𡤋M; brL𡤋L; freg};
bLo => {arM𡤊M; arL𡤊L; brM𡤋M; brL𡤋L←x1; freg};
bHi => {arM𡤊M; arL𡤊L; brM𡤋M←x1; brL𡤋L; freg};
aLo => {arM𡤊M; arL𡤊L←x1; brM𡤋M; brL𡤋L; freg};
aHi => {arM𡤊M←x1; arL𡤊L; brM𡤋M; brL𡤋L; freg};
delGamBetAlp => mode ← DragonFP.SetMode[mode, f1];
ENDCASE => Dragon.Assert[FALSE, "Unimplemented load code"] };
The following assumes that the D regs can be made transparent - Check this
It may be that load nop's may be required between the load and unloads in order to make sure that D gets clocked. The timing is such that the nop load must occur one cycle before the unload which means that it must occur two cycles before the unload in the microcode stream since unloads are driven by IPipe one cycle before loads.
[[aluDM, aluDL], aluST0] ← DragonFP.ALU[[arM,arL], [brM,brL], freg, mode];
[[mulDM, mulDL], mulST0] ← DragonFP.MUL[[arM,arL], [brM,brL], freg, mode];
f1 ← f0;
x1 ← x0;
aluCSL1 ← FPCSLdAlu3AB;
mulCSL1 ← FPCSLdMult3AB;
load1 ← load0
};
IF PhB
THEN {
TEN is tied to phB'
IF aluCSU2=unload
THEN {
EPData ← Dragon.LTD[aluZ];
EPFaultB ← aluST1;
IF log #
IO.noWhereStream
THEN {
log.PutF["\n%5g", IO.card[ Dragon.LFD[InstrCountAB] ] ];
log.PutF[" FP-Alu:%08x", IO.card[ Dragon.LFD[EPData] ] ];
log.PutF[" Status:%01x", IO.card[ LOOPHOLE[aluST1, CARDINAL] ] ] } };
IF mulCSU2=unload
THEN {
EPData ← Dragon.LTD[mulZ];
EPFaultB ← mulST1;
IF log #
IO.noWhereStream
THEN {
log.PutF["\n%5g", IO.card[ Dragon.LFD[InstrCountAB] ] ];
log.PutF[" FP-Mul:%08x", IO.card[ Dragon.LFD[EPData] ] ];
log.PutF[" Status:%01x", IO.card[ LOOPHOLE[mulST1, CARDINAL] ] ] } };
};
END;
END;
FPArgs:
PUBLIC
TYPE =
RECORD [
logRef: REF IO.STREAM];
OldFP: TYPE = RECORD [args: FPArgs, ct: CellType];
oldFP: LIST OF OldFP ← NIL;
FP:
PUBLIC
PROC [args: FPArgs]
RETURNS [ct: CellType] =
BEGIN
FOR old:
LIST
OF OldFP ← oldFP, old.rest
WHILE old #
NIL
DO
IF old.first.args = args THEN RETURN [old.first.ct]
ENDLOOP;
ct ← RoseCreate.RegisterCellType[name: FPName[args],
expandProc: FPExpand,
ioCreator: CreateFPIO, initializer: NIL,
evals: [],
tests: LIST[],
ports: CreateFPPorts[args],
driveCreator: CreateFPDrive,
typeData: NEW [FPArgs ← args]];
oldFP ← CONS[[args, ct], oldFP];
END;
FPName:
PROC [args: FPArgs]
RETURNS [name:
ROPE] = {
to: IO.STREAM ← IO.ROS[]; to.PutRope["FP"];
TRUSTED {PrintTV.Print[tv: AMBridge.TVForReferent[NEW [FPArgs ← args]], put: to]};
name ← IO.RopeFromROS[to]};
CreateFPPorts: PROC [args: FPArgs] RETURNS [ports: Ports] = {ports ← RoseCreate.PortsFromFile["FP.FP.rosePorts"]};
FPIORef: TYPE = REF FPIORec;
FPIORec:
TYPE =
MACHINE
DEPENDENT
RECORD [
FPCSLdAlu3AB(0): CSLoad,
FPCSLdMult3AB(1): CSLoad,
FPCSUnAlu2AB(2): CSUnload,
FPCSUnMult2AB(3): CSUnload,
EPFaultB(4): PBusFaults,
EPData(5): ARRAY [0..2) OF CARDINAL,
KBus(7): ARRAY [0..2) OF CARDINAL,
PhA(9): BOOLEAN,
PhB(10): BOOLEAN,
InstrCountAB(11): ARRAY [0..2) OF CARDINAL];
FPDriveRef: TYPE = REF FPDriveRec;
FPDriveRec: TYPE = RECORD [tag: DriveTagType, s: PACKED ARRAY FPPort OF DriveLevel];
FPPort:
TYPE =
MACHINE
DEPENDENT {
FPCSLdAlu3AB, FPCSLdMult3AB, FPCSUnAlu2AB, FPCSUnMult2AB, EPFaultB, EPData, KBus, PhA, PhB, InstrCountAB, (15)};
CreateFPIO:
PROC [ct: CellType]
RETURNS [ioAsAny:
REF
ANY]
--IOCreator-- = {
ioAsAny ← NEW[FPIORec];
};
CreateFPDrive:
PROC [ct: CellType]
RETURNS [driveAsAny:
REF
ANY]
--DriveCreator-- = {
driveAsAny ← NEW[FPDriveRec];
};
FPExpand:
PROC [thisCell: Cell, to: ExpansionReceiver]
--ExpandProc-- = {
args:
REF FPArgs ←
NARROW[thisCell.type.typeData];
{OPEN args;
PrivateLookupNode: PROC [name: ROPE] RETURNS [node: Node] = {node ← RoseCreate.LookupNode[from: thisCell, path: LIST[name]]};
FPCSLdAlu3AB: Node ← PrivateLookupNode["FPCSLdAlu3AB"];
FPCSLdMult3AB: Node ← PrivateLookupNode["FPCSLdMult3AB"];
FPCSUnAlu2AB: Node ← PrivateLookupNode["FPCSUnAlu2AB"];
FPCSUnMult2AB: Node ← PrivateLookupNode["FPCSUnMult2AB"];
EPFaultB: Node ← PrivateLookupNode["EPFaultB"];
EPData: Node ← PrivateLookupNode["EPData"];
KBus: Node ← PrivateLookupNode["KBus"];
PhA: Node ← PrivateLookupNode["PhA"];
PhB: Node ← PrivateLookupNode["PhB"];
InstrCountAB: Node ← PrivateLookupNode["InstrCountAB"];
others: SymbolTable ← RoseCreate.GetOthers[otherss, "FP"];
[] ← to.class.CellInstance[erInstance: to.instance, instanceName: "fpAlu", typeName: FPDevice[[type:Alu]].name, other: RoseCreate.GetOther[others, "fpAlu"], interfaceNodes: "CSLd3AB:FPCSLdAlu3AB, CSUn2AB:FPCSUnAlu2AB"];
[] ← to.class.CellInstance[erInstance: to.instance, instanceName: "fpMul", typeName: FPDevice[[type:Mul]].name, other: RoseCreate.GetOther[others, "fpMul"], interfaceNodes: "CSLd3AB:FPCSLdMult3AB, CSUn2AB:FPCSUnMult2AB"];
};
};
explicitly requested CEDAR:
log: IO.STREAM ← IO.noWhereStream;
clocked: BOOL ← FALSE;
RegisterCells[];
END.