<> <> <> <<>> DIRECTORY Core, CoreClasses, CoreCreate, CoreFlat, Ports, Rosemary, RosemaryUser, SCLogic, SCParms; <<>> SCBlockAssemblyRegisterImpl: CEDAR PROGRAM IMPORTS CoreClasses, CoreCreate, CoreFlat, Ports, Rosemary, SCParms EXPORTS SCLogic ~ BEGIN OPEN SCLogic; <> NumBitsPerWord: NAT = SCParms.numBitsPerWord; NumBitsPerCycle: NAT = SCParms.numBitsPerCycle; NumWordsPerCycle: NAT = SCParms.numWordsPerCycle; NumWordsPerLine: NAT = SCParms.numWordsPerLine; LogNumWordsPerLine: NAT = SCParms.logNumWordsPerLine; NumCyclesPerLine: NAT = SCParms.numCyclesPerLine; LogNumCyclesPerLine: NAT = SCParms.logNumCyclesPerLine; NumBitsPerLine: NAT = SCParms.numBitsPerLine; <<>> InternalState: TYPE = RECORD [ bar: LevelSequence, en: LevelSequence ]; State: TYPE = REF StateRec; StateRec: TYPE = RECORD [ bCycleAdrs: LevelSequence, master: InternalState, slave: InternalState ]; <> CycleIn, BCtlBlkWt5, BCycle0, BCycle1, BlkWtData, Clock: NAT; <> SCBlockAssemblyRegister: PUBLIC PROC [] RETURNS [ct: CellType] = { public: Wire _ CoreCreate.WireList[LIST[CoreCreate.Seq["CycleIn", NumBitsPerCycle], CoreCreate.Seq["BlkWtData", NumBitsPerLine], "BCtlBlkWt5", "BCycle0", "BCycle1", "Clock"]]; ct _ CoreClasses.CreateUnspecified[public: public]; [] _ Rosemary.BindCellType[cellType: ct, roseClassName: myBlockAssRegName]; [] _ CoreFlat.CellTypeCutLabels[ct, "Logic"]; Ports.InitPorts[ct, ls, none, "CycleIn"]; Ports.InitPorts[ct, l, none, "BCtlBlkWt5", "BCycle0", "BCycle1", "Clock"]; Ports.InitPorts[ct, ls, drive, "BlkWtData"]; }; <> Init: Rosemary.InitProc = { <<--PROC [cellType: Core.CellType, p: Ports.Port, oldStateAny: REF ANY _ NIL] RETURNS [stateAny: REF ANY _ NIL]-->> s: State; IF oldStateAny=NIL THEN { s _ NEW [StateRec]; s.bCycleAdrs _ NEW [LevelSequenceRec[LogNumCyclesPerLine]]; s.master.bar _ NEW [LevelSequenceRec[NumBitsPerLine]]; s.master.en _ NEW [LevelSequenceRec[NumCyclesPerLine]]; s.slave.bar _ NEW [LevelSequenceRec[NumBitsPerLine]]; s.slave.en _ NEW [LevelSequenceRec[NumCyclesPerLine]]; } ELSE s _ NARROW [oldStateAny, State]; Ports.SetLS[s.bCycleAdrs, X]; Ports.SetLS[s.master.bar, X]; Ports.SetLS[s.master.en, X]; Ports.SetLS[s.slave.bar, X]; Ports.SetLS[s.slave.en, X]; [CycleIn, BCtlBlkWt5, BCycle0, BCycle1, BlkWtData, Clock] _ Ports.PortIndexes[cellType.public, "CycleIn", "BCtlBlkWt5", "BCycle0", "BCycle1", "BlkWtData", "Clock"]; stateAny _ s; }; Simple: Rosemary.EvalProc = { s: State _ NARROW[stateAny]; IF NOT clockEval THEN SELECT p[Clock].l FROM L => { numEnablesHigh: NAT _ 0; FOR cycle: NAT IN [0..NumCyclesPerLine) DO <> IF p[BCycle0].l=H OR p[BCtlBlkWt5].l=H THEN s.master.en[cycle] _ L ELSE { prevCycle: INT; FOR i: NAT IN [0..LogNumCyclesPerLine) DO s.bCycleAdrs[i] _ p[CycleIn].ls[NumBitsPerCycle-NumWordsPerCycle*(LogNumWordsPerLine-i)+1]; ENDLOOP; prevCycle _ (cycle-1) MOD NumCyclesPerLine; IF prevCycle<0 THEN prevCycle _ NumCyclesPerLine-1; IF (p[BCycle1].l=H AND Ports.LSToC[s.bCycleAdrs]=cycle) OR s.slave.en[prevCycle]=H THEN s.master.en[cycle] _ H ELSE s.master.en[cycle] _ L }; <> SELECT s.slave.en[cycle] FROM H => { IF (numEnablesHigh _ numEnablesHigh+1) > 1 THEN ERROR; FOR i: NAT IN [0..NumBitsPerWord) DO s.master.bar[i*NumWordsPerLine+NumWordsPerCycle*cycle] _ p[CycleIn].ls[2*i]; s.master.bar[i*NumWordsPerLine+NumWordsPerCycle*cycle+1] _ p[CycleIn].ls[2*i+1] ENDLOOP; }; X => { FOR i: NAT IN [0..NumBitsPerWord) DO s.master.bar[i*NumWordsPerLine+NumWordsPerCycle*cycle] _ X; s.master.bar[i*NumWordsPerLine+NumWordsPerCycle*cycle+1] _ X ENDLOOP; }; ENDCASE ENDLOOP; }; H => { Ports.CopyLS[s.master.en, s.slave.en]; Ports.CopyLS[s.master.bar, s.slave.bar]; }; X => { Ports.SetLS[s.master.en, X]; Ports.SetLS[s.master.bar, X]; Ports.SetLS[s.slave.en, X]; Ports.SetLS[s.slave.bar, X]; }; ENDCASE => ERROR; Ports.CopyLS[s.slave.bar, p[BlkWtData].ls] }; myBlockAssRegName: ROPE = Rosemary.Register[roseClassName: "SCBlockAssemblyRegister", init: Init, evalSimple: Simple, scheduleIfClockEval: TRUE]; END. <<>>