MSIImpl.mesa
Copyright © 1986 by Xerox Corporation. All rights reserved.
Barth, October 10, 1986 5:34:30 pm PDT
Last Edited by: Louis Monier August 7, 1986 8:14:58 pm PDT
DIRECTORY BitOps, CoreClasses, CoreCreate, CoreFlat, CoreProperties, MSI, Ports, Rosemary;
MSIImpl: CEDAR PROGRAM
IMPORTS BitOps, CoreClasses, CoreCreate, CoreFlat, CoreProperties, Ports, Rosemary
EXPORTS MSI
= BEGIN OPEN MSI, CoreCreate;
Quick fix so that it compiles; probably wrong. --LMM
Extract the xth bit in the interger N
Warning: bit 0 is the LOW order bit (lsb)
XthBitOfN: PROC [x, n: INT] RETURNS [BOOL] ~ {
RETURN[BitOps.EBFD[container: n, bitPosition: 31-x]];
};
Latch
LatchName: ROPE = Rosemary.Register[roseClassName: "Latch", init: LatchInit, evalSimple: LatchSimple];
LatchVdd: NAT = 0;
LatchGnd: NAT = 1;
LatchLoad: NAT = 2;
LatchInput: NAT = 3;
LatchOutput: NAT = 4;
Latch: PUBLIC PROC RETURNS [ct: CellType] = {
ct ← CoreClasses.CreateUnspecified[
name: LatchName,
public: Wires["Vdd", "Gnd", "Load", "Input", "Output"]];
[] ← Rosemary.BindCellType[cellType: ct, roseClassName: LatchName];
[] ← CoreFlat.CellTypeCutLabels[ct, "MSI"];
[] ← Ports.InitPort[wire: ct.public[LatchVdd], levelType: l];
[] ← Ports.InitPort[wire: ct.public[LatchGnd], levelType: l];
[] ← Ports.InitPort[wire: ct.public[LatchLoad], levelType: l];
[] ← Ports.InitPort[wire: ct.public[LatchInput], levelType: l];
[] ← Ports.InitPort[wire: ct.public[LatchOutput], levelType: l, initDrive: drive];
};
LatchInit: Rosemary.InitProc = {
state: REF Ports.Level ← NEW[Ports.Level];
state^ ← X;
stateAny ← state;
};
LatchSimple: Rosemary.EvalProc = {
state: REF Ports.Level ← NARROW[stateAny];
SELECT p[LatchLoad].l FROM
H => state^ ← p[LatchInput].l;
X => IF state^#p[LatchInput].l THEN state^ ← X;
ENDCASE;
p[LatchOutput].l ← state^;
};
Register
RegisterName: ROPE = Rosemary.Register[roseClassName: "Register", init: RegisterInit, evalSimple: RegisterSimple];
RegVdd: NAT = 0;
RegGnd: NAT = 1;
RegLoad: NAT = 2;
RegInput: NAT = 3;
RegOutput: NAT = 4;
Register: PUBLIC PROC [b: NAT] RETURNS [ct: CellType] = {
ct ← CoreClasses.CreateUnspecified[
name: RegisterName,
public: Wires["Vdd", "Gnd", "Load", Seq["Input", b], Seq["Output", b]]];
[] ← Rosemary.BindCellType[cellType: ct, roseClassName: RegisterName];
[] ← CoreFlat.CellTypeCutLabels[ct, "MSI"];
[] ← Ports.InitPort[wire: ct.public[RegVdd], levelType: l];
[] ← Ports.InitPort[wire: ct.public[RegGnd], levelType: l];
[] ← Ports.InitPort[wire: ct.public[RegInput], levelType: ls];
[] ← Ports.InitPort[wire: ct.public[RegLoad], levelType: l];
[] ← Ports.InitPort[wire: ct.public[RegOutput], levelType: ls, initDrive: drive];
};
RegisterInit: Rosemary.InitProc = {
size: NAT ← p[RegInput].ls.size;
state: Ports.LevelSequence ← NEW[Ports.LevelSequenceRec[size]];
FOR i: NAT IN [0..size) DO state[i] ← X; ENDLOOP;
stateAny ← state;
};
RegisterSimple: Rosemary.EvalProc = {
state: Ports.LevelSequence ← NARROW[stateAny];
SELECT p[RegLoad].l FROM
H => FOR i: NAT IN [0..p[RegInput].ls.size) DO
state[i] ← p[RegInput].ls[i];
ENDLOOP;
X => FOR i: NAT IN [0..p[RegInput].ls.size) DO
IF state[i]#p[RegInput].ls[i] THEN state[i] ← X;
ENDLOOP;
ENDCASE;
FOR i: NAT IN [0..p[RegOutput].ls.size) DO
p[RegOutput].ls[i] ← state[i];
ENDLOOP;
};
Constant
ConstantName: ROPE = Rosemary.Register[roseClassName: "Constant", init: ConstantInit, evalSimple: ConstantSimple];
ConstantProp: ATOM = CoreProperties.RegisterProperty[prop: $MSIConstant];
ConstantVdd: NAT = 0;
ConstantGnd: NAT = 1;
ConstantOutput: NAT = 2;
Constant: PUBLIC PROC [b: NAT, v: INT] RETURNS [ct: CellType] = {
ct ← CoreClasses.CreateUnspecified[
name: ConstantName,
public: Wires["Vdd", "Gnd", Seq["Output", b]]];
[] ← Rosemary.BindCellType[cellType: ct, roseClassName: ConstantName];
[] ← CoreFlat.CellTypeCutLabels[ct, "MSI"];
[] ← Ports.InitPort[wire: ct.public[ConstantVdd], levelType: l];
[] ← Ports.InitPort[wire: ct.public[ConstantGnd], levelType: l];
[] ← Ports.InitPort[wire: ct.public[ConstantOutput], levelType: ls, initDrive: drive];
CoreProperties.PutCellTypeProp[ct, ConstantProp, NEW[INT ← v]];
};
ConstantInit: Rosemary.InitProc = {
stateAny ← CoreProperties.GetCellTypeProp[cellType, ConstantProp];
};
ConstantSimple: Rosemary.EvalProc = {
state: REF INTNARROW[stateAny];
bits: NAT ← p[ConstantOutput].ls.size;
FOR i: NAT IN [0..bits) DO
p[ConstantOutput].ls[i] ← IF XthBitOfN[x: bits-1-i, n: state^] THEN H ELSE L;
ENDLOOP;
};
Multiplexor
MultiplexorName: ROPE = Rosemary.Register[roseClassName: "Multiplexor", evalSimple: MultiplexorSimple];
MultiplexorSelect: NAT = 0;
MultiplexorInput: NAT = 1;
MultiplexorOutput: NAT = 2;
Multiplexor: PUBLIC PROC [i: NAT ← 2] RETURNS [ct: CellType] = {
ct ← CoreClasses.CreateUnspecified[
name: MultiplexorName,
public: Wires[Seq["Select", i], Seq["Input", i], "Output"]];
[] ← Rosemary.BindCellType[cellType: ct, roseClassName: MultiplexorName];
[] ← CoreFlat.CellTypeCutLabels[ct, "MSI"];
[] ← Ports.InitPort[wire: ct.public[MultiplexorSelect], levelType: ls];
[] ← Ports.InitPort[wire: ct.public[MultiplexorInput], levelType: ls];
[] ← Ports.InitPort[wire: ct.public[MultiplexorOutput], levelType: l, initDrive: drive];
};
MultiplexorSimple: Rosemary.EvalProc = {
foundH: BOOLFALSE;
FOR i: NAT IN [0..p[MultiplexorSelect].ls.size) DO
SELECT p[MultiplexorSelect].ls[i] FROM
X => {p[MultiplexorOutput].l ← X; EXIT};
H => IF foundH THEN {p[MultiplexorOutput].l ← X; EXIT} ELSE {
foundH ← TRUE;
p[MultiplexorOutput].l ← p[MultiplexorInput].ls[i];
};
ENDCASE;
ENDLOOP;
IF NOT foundH THEN p[MultiplexorOutput].l ← X;
};
BusMultiplexor
BusMultiplexorName: ROPE = Rosemary.Register[roseClassName: "BusMultiplexor", evalSimple: BusMultiplexorSimple];
BusMultiplexorSelect: NAT = 0;
BusMultiplexorInput: NAT = 1;
BusMultiplexorOutput: NAT = 2;
BusMultiplexor: PUBLIC PROC [b: NAT, i: NAT ← 2] RETURNS [ct: CellType] = {
ct ← CoreClasses.CreateUnspecified[
name: BusMultiplexorName,
public: Wires[Seq["Select", i], Seq["Input", i, Seq[size: b]], Seq["Output", b]]];
[] ← Rosemary.BindCellType[cellType: ct, roseClassName: BusMultiplexorName];
[] ← CoreFlat.CellTypeCutLabels[ct, "MSI"];
[] ← Ports.InitPort[wire: ct.public[BusMultiplexorSelect], levelType: ls];
FOR in: NAT IN [0..i) DO
[] ← Ports.InitPort[wire: ct.public[BusMultiplexorInput][in], levelType: ls];
ENDLOOP;
[] ← Ports.InitPort[wire: ct.public[BusMultiplexorOutput], levelType: ls, initDrive: drive];
};
BusMultiplexorSimple: Rosemary.EvalProc = {
SetX: PROC = {
FOR bit: NAT IN [0..p[BusMultiplexorOutput].ls.size) DO
p[BusMultiplexorOutput].ls[bit] ← X;
ENDLOOP;
};
foundH: BOOLFALSE;
FOR i: NAT IN [0..p[BusMultiplexorSelect].ls.size) DO
SELECT p[BusMultiplexorSelect].ls[i] FROM
X => {SetX[]; EXIT};
H => IF foundH THEN {SetX[]; EXIT} ELSE {
foundH ← TRUE;
FOR bit: NAT IN [0..p[BusMultiplexorOutput].ls.size) DO
p[BusMultiplexorOutput].ls[bit] ← p[BusMultiplexorInput][i].ls[bit];
ENDLOOP;
};
ENDCASE;
ENDLOOP;
IF NOT foundH THEN SetX[];
};
Buffers
BuffersName: ROPE = Rosemary.Register[roseClassName: "Buffers", evalSimple: BuffersSimple];
BuffersVdd: NAT = 0;
BuffersGnd: NAT = 1;
BuffersInput: NAT = 2;
BuffersOutput: NAT = 3;
Buffers: PUBLIC PROC [b: NAT] RETURNS [ct: CellType] = {
ct ← CoreClasses.CreateUnspecified[
name: BuffersName,
public: Wires["Vdd", "Gnd", Seq["Input", b], Seq["Output", b]]];
[] ← Rosemary.BindCellType[cellType: ct, roseClassName: BuffersName];
[] ← CoreFlat.CellTypeCutLabels[ct, "MSI"];
[] ← Ports.InitPort[wire: ct.public[BuffersVdd], levelType: l];
[] ← Ports.InitPort[wire: ct.public[BuffersGnd], levelType: l];
[] ← Ports.InitPort[wire: ct.public[BuffersInput], levelType: ls];
[] ← Ports.InitPort[wire: ct.public[BuffersOutput], levelType: ls, initDrive: drive];
};
BuffersSimple: Rosemary.EvalProc = {
FOR i: NAT IN [0..p[BuffersInput].ls.size) DO
p[BuffersOutput].ls[i] ← p[BuffersInput].ls[i];
ENDLOOP;
};
TristateBuffers
TristateBuffersName: ROPE = Rosemary.Register[roseClassName: "TristateBuffers", evalSimple: TristateBuffersSimple];
TristateBuffersVdd: NAT = 0;
TristateBuffersGnd: NAT = 1;
TristateBuffersDrive: NAT = 2;
TristateBuffersInput: NAT = 3;
TristateBuffersOutput: NAT = 4;
TristateBuffers: PUBLIC PROC [b: NAT] RETURNS [ct: CellType] = {
ct ← CoreClasses.CreateUnspecified[
name: TristateBuffersName,
public: Wires["Vdd", "Gnd", "Drive", Seq["Input", b], Seq["Output", b]]];
[] ← Rosemary.BindCellType[cellType: ct, roseClassName: TristateBuffersName];
[] ← CoreFlat.CellTypeCutLabels[ct, "MSI"];
[] ← Ports.InitPort[wire: ct.public[TristateBuffersVdd], levelType: l];
[] ← Ports.InitPort[wire: ct.public[TristateBuffersGnd], levelType: l];
[] ← Ports.InitPort[wire: ct.public[TristateBuffersDrive], levelType: l];
[] ← Ports.InitPort[wire: ct.public[TristateBuffersInput], levelType: ls];
[] ← Ports.InitPort[wire: ct.public[TristateBuffersOutput], levelType: ls];
};
TristateBuffersSimple: Rosemary.EvalProc = {
p[TristateBuffersOutput].d ← IF p[TristateBuffersDrive].l#L THEN drive ELSE none;
FOR i: NAT IN [0..p[TristateBuffersInput].ls.size) DO
p[TristateBuffersOutput].ls[i] ← p[TristateBuffersInput].ls[i];
ENDLOOP;
};
Adder
AdderName: ROPE = Rosemary.Register[roseClassName: "Adder", evalSimple: AdderSimple];
AdderVdd: NAT = 0;
AdderGnd: NAT = 1;
AdderCarryIn: NAT = 2;
AdderA: NAT = 3;
AdderB: NAT = 4;
AdderSum: NAT = 5;
AdderCarryOut: NAT = 6;
Adder: PUBLIC PROC [b: NAT] RETURNS [ct: CellType] = {
ct ← CoreClasses.CreateUnspecified[
name: AdderName,
public: Wires["Vdd", "Gnd", "CarryIn", Seq["A", b], Seq["B", b], Seq["Sum", b], "CarryOut"]];
[] ← Rosemary.BindCellType[cellType: ct, roseClassName: AdderName];
[] ← CoreFlat.CellTypeCutLabels[ct, "MSI"];
[] ← Ports.InitPort[wire: ct.public[AdderVdd], levelType: l];
[] ← Ports.InitPort[wire: ct.public[AdderGnd], levelType: l];
[] ← Ports.InitPort[wire: ct.public[AdderCarryIn], levelType: l];
[] ← Ports.InitPort[wire: ct.public[AdderA], levelType: ls];
[] ← Ports.InitPort[wire: ct.public[AdderB], levelType: ls];
[] ← Ports.InitPort[wire: ct.public[AdderSum], levelType: ls, initDrive: drive];
[] ← Ports.InitPort[wire: ct.public[AdderCarryOut], levelType: l, initDrive: drive];
};
AdderSimple: Rosemary.EvalProc = {
carry: Ports.Level ← p[AdderCarryIn].l;
FOR i: NAT DECREASING IN [0..p[AdderA].ls.size) DO
a: Ports.Level ← p[AdderA].ls[i];
b: Ports.Level ← p[AdderB].ls[i];
IF carry=X OR a=X OR b=X THEN {
p[AdderSum].ls[i] ← X;
carry ← X;
}
ELSE {
ba: BOOLIF a=H THEN TRUE ELSE FALSE;
bb: BOOLIF b=H THEN TRUE ELSE FALSE;
bc: BOOLIF carry=H THEN TRUE ELSE FALSE;
p[AdderSum].ls[i] ← IF BXor[ba, BXor[bb, bc]] THEN H ELSE L;
carry ← IF (ba AND (bb OR bc)) OR (bb AND bc) THEN H ELSE L;
};
ENDLOOP;
p[AdderCarryOut].l ← carry;
};
Comparator
ComparatorName: ROPE = Rosemary.Register[roseClassName: "Comparator", evalSimple: ComparatorSimple];
CmpVdd: NAT = 0;
CmpGnd: NAT = 1;
CmpA: NAT = 2;
CmpB: NAT = 3;
CmpAEqB: NAT = 4;
Comparator: PUBLIC PROC [b: NAT] RETURNS [ct: CellType] = {
ct ← CoreClasses.CreateUnspecified[
name: ComparatorName,
public: Wires["Vdd", "Gnd", Seq["A", b], Seq["B", b], "AEqB"]];
[] ← Rosemary.BindCellType[cellType: ct, roseClassName: ComparatorName];
[] ← CoreFlat.CellTypeCutLabels[ct, "MSI"];
[] ← Ports.InitPort[wire: ct.public[CmpVdd], levelType: l];
[] ← Ports.InitPort[wire: ct.public[CmpGnd], levelType: l];
[] ← Ports.InitPort[wire: ct.public[CmpA], levelType: ls];
[] ← Ports.InitPort[wire: ct.public[CmpB], levelType: ls];
[] ← Ports.InitPort[wire: ct.public[CmpAEqB], levelType: l, initDrive: drive];
};
ComparatorSimple: Rosemary.EvalProc = {
p[CmpAEqB].l ← H;
FOR i: NAT IN [0..p[CmpA].ls.size) DO
IF p[CmpA].ls[i]#p[CmpB].ls[i] THEN p[CmpAEqB].l ← L;
IF p[CmpA].ls[i]=X OR p[CmpB].ls[i]=X THEN {p[CmpAEqB].l ← X; EXIT};
ENDLOOP;
};
Decoders
DecoderName: ROPE = Rosemary.Register[roseClassName: "Decoder", evalSimple: DecoderSimple];
DecoderVdd: NAT = 0;
DecoderGnd: NAT = 1;
DecoderAddress: NAT = 2;
DecoderSelect: NAT = 3;
ClockedDecoderClock: NAT = 4;
Decoder: PUBLIC PROC [a: NAT, s: NAT ← 0] RETURNS [ct: CellType] = {
IF s=0 THEN s ← BitOps.TwoToThe[a];
ct ← CoreClasses.CreateUnspecified[
name: DecoderName,
public: Wires["Vdd", "Gnd", Seq["Address", a], Seq["Select", s]]];
InitDecoder[ct];
};
ClockedDecoder: PUBLIC PROC [a: NAT, s: NAT ← 0] RETURNS [ct: CellType] = {
IF s=0 THEN s ← BitOps.TwoToThe[a];
ct ← CoreClasses.CreateUnspecified[
name: "ClockedDecoder",
public: Wires["Vdd", "Gnd", Seq["Address", a], Seq["Select", s], "Clock"]];
InitDecoder[ct];
[] ← Ports.InitPort[wire: ct.public[ClockedDecoderClock], levelType: l];
};
InitDecoder: PROC [ct: CellType] = {
[] ← Rosemary.BindCellType[cellType: ct, roseClassName: DecoderName];
[] ← CoreFlat.CellTypeCutLabels[ct, "MSI"];
[] ← Ports.InitPort[wire: ct.public[DecoderVdd], levelType: l];
[] ← Ports.InitPort[wire: ct.public[DecoderGnd], levelType: l];
[] ← Ports.InitPort[wire: ct.public[DecoderAddress], levelType: ls];
[] ← Ports.InitPort[wire: ct.public[DecoderSelect], levelType: ls, initDrive: drive];
};
DecoderSimple: Rosemary.EvalProc = {
SetLevel: PROC[l: Ports.Level] = {
FOR i: NAT IN [0..p[DecoderSelect].ls.size) DO
p[DecoderSelect].ls[i] ← l;
ENDLOOP;
};
clocked: BOOL ← p.size-1=ClockedDecoderClock;
IF clocked AND p[ClockedDecoderClock].l=X THEN SetLevel[X]
ELSE {
SetLevel[L];
IF NOT clocked OR p[ClockedDecoderClock].l=H THEN {
bits: NAT ← p[DecoderAddress].ls.size;
address: NAT ← 0;
FOR i: NAT IN [0..bits) DO
SELECT p[DecoderAddress].ls[i] FROM
L => address ← 2*address;
H => address ← (2*address) + 1;
X => SetLevel[X];
ENDCASE => ERROR;
ENDLOOP;
IF address>p[DecoderSelect].ls.size THEN SIGNAL Rosemary.Stop[];
p[DecoderSelect].ls[address] ← H;
};
};
};
ShiftRegister
ShiftRegisterName: ROPE = Rosemary.Register[roseClassName: "ShiftRegister", init: ShiftRegisterInit, evalSimple: ShiftRegisterSimple];
ShiftRegisterVdd: NAT = 0;
ShiftRegisterGnd: NAT = 1;
ShiftRegisterShiftA: NAT = 2;
ShiftRegisterShiftB: NAT = 3;
ShiftRegisterLoadA: NAT = 4;
ShiftRegisterLeftNRight: NAT = 5;
ShiftRegisterLeftInput: NAT = 6;
ShiftRegisterRightInput: NAT = 7;
ShiftRegisterInput: NAT = 8;
ShiftRegisterOutput: NAT = 9;
ShiftRegister: PUBLIC PROC [b: NAT] RETURNS [ct: CellType] = {
ct ← CoreClasses.CreateUnspecified[
name: ShiftRegisterName,
public: Wires["Vdd", "Gnd", "ShiftA", "ShiftB", "LoadA", "LeftNRight", "LeftInput", "RightInput", Seq["Input", b], Seq["Output", b]]];
[] ← Rosemary.BindCellType[cellType: ct, roseClassName: ShiftRegisterName];
[] ← CoreFlat.CellTypeCutLabels[ct, "MSI"];
[] ← Ports.InitPort[wire: ct.public[ShiftRegisterVdd], levelType: l];
[] ← Ports.InitPort[wire: ct.public[ShiftRegisterGnd], levelType: l];
[] ← Ports.InitPort[wire: ct.public[ShiftRegisterShiftA], levelType: l];
[] ← Ports.InitPort[wire: ct.public[ShiftRegisterShiftB], levelType: l];
[] ← Ports.InitPort[wire: ct.public[ShiftRegisterLoadA], levelType: l];
[] ← Ports.InitPort[wire: ct.public[ShiftRegisterLeftNRight], levelType: l];
[] ← Ports.InitPort[wire: ct.public[ShiftRegisterLeftInput], levelType: l];
[] ← Ports.InitPort[wire: ct.public[ShiftRegisterRightInput], levelType: l];
[] ← Ports.InitPort[wire: ct.public[ShiftRegisterInput], levelType: ls];
[] ← Ports.InitPort[wire: ct.public[ShiftRegisterOutput], levelType: ls, initDrive: drive];
};
ShiftRegisterState: TYPE = REF ShiftRegisterStateRec;
ShiftRegisterStateRec: TYPE = RECORD [
a: Ports.LevelSequence ← NIL,
b: Ports.LevelSequence ← NIL];
ShiftRegisterInit: Rosemary.InitProc = {
state: ShiftRegisterState ← NEW[ShiftRegisterStateRec];
size: NAT ← p[ShiftRegisterOutput].ls.size;
state.a ← NEW[Ports.LevelSequenceRec[size]];
state.b ← NEW[Ports.LevelSequenceRec[size]];
FOR i: NAT IN [0..size) DO state.a[i] ← state.b[i] ← X; ENDLOOP;
stateAny ← state;
};
ShiftRegisterSimple: Rosemary.EvalProc = {
SetX: PROC = {
FOR bit: NAT IN [0..sizeMOne] DO
state.a[bit] ← state.b[bit] ← p[ShiftRegisterOutput].ls[bit] ← X;
ENDLOOP;
};
state: ShiftRegisterState ← NARROW[stateAny];
sizeMOne: NAT ← p[ShiftRegisterInput].ls.size-1;
IF p[ShiftRegisterShiftA].l=X OR p[ShiftRegisterShiftB].l=X OR p[ShiftRegisterLoadA].l=X OR (p[ShiftRegisterShiftA].l#L AND p[ShiftRegisterLoadA].l#L) THEN SetX[]
ELSE {
IF p[ShiftRegisterShiftA].l=H THEN {
IF p[ShiftRegisterLeftNRight].l=X THEN SetX[]
ELSE {
IF p[ShiftRegisterLeftNRight].l=H THEN {
FOR i: NAT IN [0..sizeMOne) DO
state.a[i] ← state.b[i+1];
ENDLOOP;
state.a[sizeMOne] ← p[ShiftRegisterRightInput].l;
}
ELSE {
FOR i: NAT DECREASING IN [0..sizeMOne) DO
state.a[i+1] ← state.b[i];
ENDLOOP;
state.a[0] ← p[ShiftRegisterLeftInput].l;
};
};
};
IF p[ShiftRegisterLoadA].l=H THEN {
FOR i: NAT IN [0..sizeMOne] DO
state.a[i] ← p[ShiftRegisterInput].ls[i];
ENDLOOP;
};
IF p[ShiftRegisterShiftB].l=H THEN {
FOR i: NAT IN [0..sizeMOne] DO
state.b[i] ← state.a[i];
ENDLOOP;
};
FOR i: NAT IN [0..sizeMOne] DO
p[ShiftRegisterOutput].ls[i] ← state.b[i];
ENDLOOP;
};
};
Counter
CounterName: ROPE = Rosemary.Register[roseClassName: "Counter", init: CounterInit, evalSimple: CounterSimple];
CounterVdd: NAT = 0;
CounterGnd: NAT = 1;
CounterCountA: NAT = 2;
CounterCountB: NAT = 3;
CounterLoadA: NAT = 4;
CounterUpNDown: NAT = 5;
CounterInput: NAT = 6;
CounterOutput: NAT = 7;
Counter: PUBLIC PROC [b: NAT] RETURNS [ct: CellType] = {
ct ← CoreClasses.CreateUnspecified[
name: CounterName,
public: Wires["Vdd", "Gnd", "CountA", "CountB", "LoadA", "UpNDown", Seq["Input", b], Seq["Output", b]]];
[] ← Rosemary.BindCellType[cellType: ct, roseClassName: CounterName];
[] ← CoreFlat.CellTypeCutLabels[ct, "MSI"];
[] ← Ports.InitPort[wire: ct.public[CounterVdd], levelType: l];
[] ← Ports.InitPort[wire: ct.public[CounterGnd], levelType: l];
[] ← Ports.InitPort[wire: ct.public[CounterCountA], levelType: l];
[] ← Ports.InitPort[wire: ct.public[CounterCountB], levelType: l];
[] ← Ports.InitPort[wire: ct.public[CounterLoadA], levelType: l];
[] ← Ports.InitPort[wire: ct.public[CounterUpNDown], levelType: l];
[] ← Ports.InitPort[wire: ct.public[CounterInput], levelType: ls];
[] ← Ports.InitPort[wire: ct.public[CounterOutput], levelType: ls, initDrive: drive];
};
CounterState: TYPE = REF CounterStateRec;
CounterStateRec: TYPE = RECORD [
a: Ports.LevelSequence ← NIL,
b: Ports.LevelSequence ← NIL];
CounterInit: Rosemary.InitProc = {
state: CounterState ← NEW[CounterStateRec];
size: NAT ← p[CounterOutput].ls.size;
state.a ← NEW[Ports.LevelSequenceRec[size]];
state.b ← NEW[Ports.LevelSequenceRec[size]];
FOR i: NAT IN [0..size) DO state.a[i] ← state.b[i] ← X; ENDLOOP;
stateAny ← state;
};
CounterSimple: Rosemary.EvalProc = {
SetX: PROC = {
FOR bit: NAT IN [0..size) DO
state.a[bit] ← state.b[bit] ← p[CounterOutput].ls[bit] ← X;
ENDLOOP;
};
state: CounterState ← NARROW[stateAny];
size: NAT ← p[CounterInput].ls.size;
IF p[CounterCountA].l=X OR p[CounterCountB].l=X OR p[CounterLoadA].l=X OR (p[CounterCountA].l#L AND p[CounterLoadA].l#L) THEN SetX[]
ELSE {
IF p[CounterCountA].l=H THEN {
IF p[CounterUpNDown].l=X THEN SetX[]
ELSE {
IF p[CounterUpNDown].l=H THEN {
carry: Ports.Level ← H;
FOR i: NAT DECREASING IN [0..size) DO
state.a[i] ← IF carry=X OR state.b[i]=X THEN X ELSE IF BXor[carry=H, state.b[i]=H] THEN H ELSE L;
carry ← IF carry=X OR state.b[i]=X THEN X ELSE IF carry=H AND state.b[i]=H THEN H ELSE L;
ENDLOOP;
}
ELSE {
borrow: Ports.Level ← H;
FOR i: NAT DECREASING IN [0..size) DO
state.a[i] ← IF borrow=X OR state.b[i]=X THEN X ELSE IF BXor[borrow=H, state.b[i]=H] THEN H ELSE L;
borrow ← IF borrow=X OR state.b[i]=X THEN X ELSE IF borrow=H AND state.b[i]=L THEN H ELSE L;
ENDLOOP;
};
};
};
IF p[CounterLoadA].l=H THEN {
FOR i: NAT IN [0..size) DO
state.a[i] ← p[CounterInput].ls[i];
ENDLOOP;
};
IF p[CounterCountB].l=H THEN {
FOR i: NAT IN [0..size) DO
state.b[i] ← state.a[i];
ENDLOOP;
};
FOR i: NAT IN [0..size) DO
p[CounterOutput].ls[i] ← state.b[i];
ENDLOOP;
};
};
RegisterFile
RegisterFileName: ROPE = Rosemary.Register[roseClassName: "RegisterFile", init: RegisterFileInit, evalSimple: RegisterFileSimple];
RegisterFileProp: ATOM = CoreProperties.RegisterProperty[prop: $MSIRegisterFile];
RegisterFileVdd: NAT = 0;
RegisterFileGnd: NAT = 1;
RegisterFileLoad: NAT = 2;
RegisterFileAddress: NAT = 3;
RegisterFileInput: NAT = 4;
RegisterFileOutput: NAT = 5;
RegisterFile: PUBLIC PROC [b: NAT, a: NAT, w: NAT ← 0] RETURNS [ct: CellType] = {
ct ← CoreClasses.CreateUnspecified[
name: RegisterFileName,
public: Wires["Vdd", "Gnd", "Load", Seq["Address", a], Seq["Input", b], Seq["Output", b]]];
[] ← Rosemary.BindCellType[cellType: ct, roseClassName: RegisterFileName];
[] ← CoreFlat.CellTypeCutLabels[ct, "MSI"];
[] ← Ports.InitPort[wire: ct.public[RegisterFileVdd], levelType: l];
[] ← Ports.InitPort[wire: ct.public[RegisterFileGnd], levelType: l];
[] ← Ports.InitPort[wire: ct.public[RegisterFileLoad], levelType: l];
[] ← Ports.InitPort[wire: ct.public[RegisterFileAddress], levelType: ls];
[] ← Ports.InitPort[wire: ct.public[RegisterFileInput], levelType: ls];
[] ← Ports.InitPort[wire: ct.public[RegisterFileOutput], levelType: ls, initDrive: drive];
IF w=0 THEN w ← BitOps.TwoToThe[a];
CoreProperties.PutCellTypeProp[ct, RegisterFileProp, NEW[NAT ← w]];
};
RegisterFileState: TYPE = REF RegisterFileStateRec;
RegisterFileStateRec: TYPE = RECORD [
bits: SEQUENCE size: NAT OF Ports.LevelSequence];
RegisterFileInit: Rosemary.InitProc = {
words: NATNARROW[CoreProperties.GetCellTypeProp[cellType, RegisterFileProp], REF NAT]^;
bits: NAT ← p[RegisterFileOutput].ls.size;
state: RegisterFileState ← NEW[RegisterFileStateRec[words]];
FOR w: NAT IN [0..words) DO
state[w] ← NEW[Ports.LevelSequenceRec[bits]];
FOR b: NAT IN [0..bits) DO
state[w][b] ← X;
ENDLOOP;
ENDLOOP;
stateAny ← state;
};
RegisterFileSimple: Rosemary.EvalProc = {
state: RegisterFileState ← NARROW[stateAny];
words: NAT ← state.size;
bits: NAT ← p[RegisterFileOutput].ls.size;
adr: NAT ← 0;
FOR a: NAT IN [0..p[RegisterFileAddress].ls.size) DO
aBit: Ports.Level ← p[RegisterFileAddress].ls[a];
IF aBit=X THEN {
IF p[RegisterFileLoad].l#L THEN FOR w: NAT IN [0..words) DO
FOR b: NAT IN [0..bits) DO
state[w][b] ← X;
ENDLOOP;
ENDLOOP;
FOR b: NAT IN [0..bits) DO
p[RegisterFileOutput].ls[b] ← X;
ENDLOOP;
EXIT;
}
ELSE adr ← 2*adr + (IF p[RegisterFileAddress].ls[a]=H THEN 1 ELSE 0);
REPEAT FINISHED => {
IF p[RegisterFileLoad].l=H THEN FOR b: NAT IN [0..bits) DO
state[adr][b] ← p[RegisterFileInput].ls[b];
ENDLOOP
ELSE IF p[RegisterFileLoad].l=X THEN FOR b: NAT IN [0..bits) DO
state[adr][b] ← X;
ENDLOOP;
FOR b: NAT IN [0..bits) DO
p[RegisterFileOutput].ls[b] ← state[adr][b];
ENDLOOP;
}
ENDLOOP;
};
MultiPortRegisterFile
MultiPortRegisterFileName: ROPE = Rosemary.Register[roseClassName: "MultiPortRegisterFile", init: MultiPortRegisterFileInit, evalSimple: MultiPortRegisterFileSimple];
MultiPortRegisterFileProp: ATOM = CoreProperties.RegisterProperty[prop: $MSIMultiPortRegisterFile];
MultiPortRegisterFileVdd: NAT = 0;
MultiPortRegisterFileGnd: NAT = 1;
MultiPortRegisterFileLoad: NAT = 2;
MultiPortRegisterFileWriteAddress: NAT = 3;
MultiPortRegisterFileReadAddress: NAT = 4;
MultiPortRegisterFileInput: NAT = 5;
MultiPortRegisterFileOutput: NAT = 6;
MultiPortRegisterFile: PUBLIC PROC [b: NAT, a: NAT, w: NAT ← 0, rp: NAT ← 1, wp: NAT ← 1] RETURNS [ct: CellType] = {
ct ← CoreClasses.CreateUnspecified[
name: MultiPortRegisterFileName,
public: Wires["Vdd", "Gnd", Seq["Load", wp], Seq["WriteAddress", wp, Seq[size: a]], Seq["ReadAddress", rp, Seq[size: a]], Seq["Input", wp, Seq[size: b]], Seq["Output", rp, Seq[size: b]]]];
[] ← Rosemary.BindCellType[cellType: ct, roseClassName: MultiPortRegisterFileName];
[] ← CoreFlat.CellTypeCutLabels[ct, "MSI"];
[] ← Ports.InitPort[wire: ct.public[MultiPortRegisterFileVdd], levelType: l];
[] ← Ports.InitPort[wire: ct.public[MultiPortRegisterFileGnd], levelType: l];
[] ← Ports.InitPort[wire: ct.public[MultiPortRegisterFileLoad], levelType: ls];
FOR port: NAT IN [0..wp) DO
[] ← Ports.InitPort[wire: ct.public[MultiPortRegisterFileWriteAddress][port], levelType: ls];
[] ← Ports.InitPort[wire: ct.public[MultiPortRegisterFileInput][port], levelType: ls];
ENDLOOP;
FOR port: NAT IN [0..rp) DO
[] ← Ports.InitPort[wire: ct.public[MultiPortRegisterFileReadAddress][port], levelType: ls];
[] ← Ports.InitPort[wire: ct.public[MultiPortRegisterFileOutput][port], levelType: ls, initDrive: drive];
ENDLOOP;
IF w=0 THEN w ← BitOps.TwoToThe[a];
CoreProperties.PutCellTypeProp[ct, MultiPortRegisterFileProp, NEW[NAT ← w]];
};
MultiPortRegisterFileState: TYPE = REF MultiPortRegisterFileStateRec;
MultiPortRegisterFileStateRec: TYPE = RECORD [
bits: SEQUENCE size: NAT OF Ports.LevelSequence];
MultiPortRegisterFileInit: Rosemary.InitProc = {
words: NATNARROW[CoreProperties.GetCellTypeProp[cellType, MultiPortRegisterFileProp], REF NAT]^;
bits: NAT ← p[MultiPortRegisterFileOutput][0].ls.size;
state: MultiPortRegisterFileState ← NEW[MultiPortRegisterFileStateRec[words]];
FOR w: NAT IN [0..words) DO
state[w] ← NEW[Ports.LevelSequenceRec[bits]];
FOR b: NAT IN [0..bits) DO
state[w][b] ← X;
ENDLOOP;
ENDLOOP;
stateAny ← state;
};
MultiPortRegisterFileSimple: Rosemary.EvalProc = {
state: MultiPortRegisterFileState ← NARROW[stateAny];
words: NAT ← state.size;
bits: NAT ← p[MultiPortRegisterFileOutput][0].ls.size;
FOR port: NAT IN [0..p[MultiPortRegisterFileInput].size) DO
adr: NAT ← 0;
FOR a: NAT IN [0..p[MultiPortRegisterFileWriteAddress][port].ls.size) DO
aBit: Ports.Level ← p[MultiPortRegisterFileWriteAddress][port].ls[a];
IF aBit=X THEN {
IF p[MultiPortRegisterFileLoad].ls[port]#L THEN FOR w: NAT IN [0..words) DO
FOR b: NAT IN [0..bits) DO
state[w][b] ← X;
ENDLOOP;
ENDLOOP;
EXIT;
}
ELSE adr ← 2*adr + (IF p[MultiPortRegisterFileWriteAddress][port].ls[a]=H THEN 1 ELSE 0);
REPEAT FINISHED => {
IF p[MultiPortRegisterFileLoad].ls[port]=H THEN FOR b: NAT IN [0..bits) DO
state[adr][b] ← p[MultiPortRegisterFileInput][port].ls[b];
ENDLOOP
ELSE IF p[MultiPortRegisterFileLoad].ls[port]=X THEN FOR b: NAT IN [0..bits) DO
state[adr][b] ← X;
ENDLOOP;
}
ENDLOOP;
ENDLOOP;
FOR port: NAT IN [0..p[MultiPortRegisterFileOutput].size) DO
adr: NAT ← 0;
FOR a: NAT IN [0..p[MultiPortRegisterFileReadAddress][port].ls.size) DO
aBit: Ports.Level ← p[MultiPortRegisterFileReadAddress][port].ls[a];
IF aBit=X THEN {
FOR b: NAT IN [0..bits) DO
p[MultiPortRegisterFileOutput][port].ls[b] ← X;
ENDLOOP;
EXIT;
}
ELSE adr ← 2*adr + (IF p[MultiPortRegisterFileReadAddress][port].ls[a]=H THEN 1 ELSE 0);
REPEAT FINISHED => {
FOR b: NAT IN [0..bits) DO
p[MultiPortRegisterFileOutput][port].ls[b] ← state[adr][b];
ENDLOOP;
}
ENDLOOP;
ENDLOOP;
};
BXor: PROC [x, y: BOOL] RETURNS [z: BOOL] = {
z ← (x AND NOT y) OR (NOT x AND y)
};
END.