//========================================================================= /// <summary> /// Initialise with an incoming msg. This interpreter now has a copy of the message. /// </summary> /// <param name="inMsg"></param> /// <returns></returns> //========================================================================= public bool loadMessage(TMsgHeader inMsg) { int iFld; bool result; if (!inMsg.Equals(null)) //if there is a message header { //need to do a cleanup in case the interpreter has any existing msg's for (iFld = 1; (iFld <= Msgs.MAX_FLDS) && (initArray[iFld - 1].fieldType != TTypedValue.TBaseType.ITYPE_EMPTY); iFld++) { if (initArray[iFld - 1].size > 0) { freeInitArrayItem(iFld); } } //take ownership of the msg header and data block msg = inMsg; //now I own the msg because I will delete it later result = true; } else { result = false; } return(result); }
/// <summary> /// Build the Complete message /// </summary> /// <param name="msgTo"></param> /// <param name="msgID"></param> /// <returns></returns> public TMsgHeader BuildCompleteMsg(uint msgTo, uint msgID) { int ptr = 0; //index in byte array msg = newMsg(Msgs.MSG_COMPLETE, msgTo, 4); addInt4(ref msg.dataPtr, ref ptr, (uint)msgID); return(msg); }
/// <summary> /// Build the GetValue message /// </summary> /// <param name="driverID"></param> /// <param name="FParentID"></param> /// <returns></returns> public TMsgHeader BuildGetValueMsg(int driverID, uint FParentID) { int ptr = 0; //index in byte array msg = newMsg(Msgs.MSG_GETVALUE, FParentID, 4); addInt4(ref msg.dataPtr, ref ptr, (uint)driverID); return(msg); }
/// <summary> /// Build the QueryValue message /// </summary> /// <param name="destCompID"></param> /// <param name="propID"></param> /// <param name="reqByID"></param> /// <returns></returns> public TMsgHeader BuildQueryValueMsg(uint destCompID, uint propID, uint reqByID) { int ptr = 0; //index in byte array msg = newMsg(Msgs.MSG_QUERYVALUE, destCompID, 8); addInt4(ref msg.dataPtr, ref ptr, propID); addInt4(ref msg.dataPtr, ref ptr, reqByID); return(msg); }
//============================================================================ /// <summary> /// Add a message to the list which is a copy of the original message header. /// </summary> /// <param name="msg">Message to copy and insert into the list.</param> //============================================================================ public virtual void addMsgToList(TMsgHeader msg) { TMsgHeader aMsg = new TMsgHeader(); aMsg = msg; //copy aMsg.dataPtr = null; msgList.Add(aMsg); ++activeCount; }
//============================================================================ /// <summary> /// Sends the unique component ID to the system that owns the component. /// </summary> /// <param name="ownerID">Owning component ID.</param> /// <param name="sCompFQN">Component name.</param> /// <param name="newID">New component ID.</param> //============================================================================ protected void sendComponentID(uint ownerID, string sCompFQN, uint newID) { registrar.addOwnerComp(ownerID, newID); interpreter.setField(Msgs.MSG_RETURNCOMPID_FQN, sCompFQN); interpreter.setField(Msgs.MSG_RETURNCOMPID_ID, newID); interpreter.createMessage(Msgs.MSG_RETURNCOMPID, ownerID); TMsgHeader newMsg = interpreter.getMsg(); //take control of this msg sendMessage(newMsg); }
//============================================================================ /// <summary> /// If there is a sequencer component, sends a commence message to it to begin /// the simulation. /// </summary> //============================================================================ protected void sendCommence() { TMsgHeader newMsg = interpreter.createMessage(Msgs.MSG_COMMENCE, sequencerID); // Normally the entire simulation runs "inside" the handling of this // message, so this seems a good place to catch any wayward exceptions try { sendMessage(newMsg); } catch (Exception e) { sendError("Exception during execution: sendCommence() " + e.Message, true); } }
private TMsgHeader newMsg(int msgType, uint destCompID, int size) { if (++runningID == 0) { ++runningID; } msg = new TMsgHeader(); msg.version = 256; //protocol version msg.msgType = (UInt16)msgType; //id of msg type msg.from = ownerCompID; //id of this component msg.to = destCompID; //sending msg to a component msg.msgID = runningID; //unique id msg.toAck = msgSpec[msgType - 1].toAck; //decide whether to acknowledge msg.nDataBytes = (uint)size; //init field msg.dataPtr = new byte[msg.nDataBytes]; return(msg); }
//========================================================================= /// <summary> /// Converts a message that has an IntPtr data field into a managed /// code version of a message. /// </summary> /// <param name="src">The unmanaged version of the message.</param> /// <returns>The new managed message structure.</returns> //========================================================================= public static TMsgHeader NativeMsgToManagedMsg(ref TNativeMsgHeader src) { TMsgHeader msgPtr = new TMsgHeader(); uint nBytes = src.nDataBytes; msgPtr.version = src.version; msgPtr.msgType = src.msgType; msgPtr.from = src.from; msgPtr.to = src.to; msgPtr.msgID = src.msgID; msgPtr.toAck = src.toAck; msgPtr.nDataBytes = nBytes; if (nBytes == 0) { msgPtr.dataPtr = null; } else { msgPtr.dataPtr = new Byte[nBytes]; Marshal.Copy(src.dataPtr, msgPtr.dataPtr, 0, (int)nBytes); } return(msgPtr); }
//============================================================================ /// <summary> /// Creates a TMsgHeaderList. /// </summary> //============================================================================ public TMessageHdrList() { msgList = new List <TMsgHeader>(); activeCount = 0; Null = new TMsgHeader(); }
//============================================================================ /// <summary> /// Test if the msg is defined. /// </summary> /// <param name="msg"></param> /// <returns>True if msg == TMessageHdrList.Null</returns> //============================================================================ public Boolean IsNull(TMsgHeader msg) { return(msg.Equals(Null)); }
//========================================================================= /// <summary> /// Construct a message with fields appropriate to the nominated message. /// All integer fields will be set to zero, all text fields to null, all /// boolean fields to false and all pointers to null. If the interpreter is /// already handling a message, it is deleted. /// </summary> /// <param name="msgType">Type of message. See Msgs class</param> /// <param name="destAddress"></param> /// <returns></returns> //========================================================================= public TMsgHeader createMessage(int msgType, uint destAddress) { int iFld, iFldType; int ptr = 0; //index in byte array // determine a unique id for this message // avoid using an ID of 0, since this is used else to flag empty buffers if (++runningID == 0) { ++runningID; } msg = new TMsgHeader(); msg.version = 256; //protocol version msg.msgType = (UInt16)msgType; //id of msg type msg.from = ownerCompID; //id of this component msg.to = destAddress; //sending msg to a component msg.msgID = runningID; //unique id msg.toAck = msgSpec[msgType - 1].toAck; //decide whether to acknowledge msg.nDataBytes = (uint)newMsgBlockSize; //init field msg.dataPtr = new byte[msg.nDataBytes]; //use all the memory that the initArray points to iFld = 1; iFldType = msgSpec[msg.msgType - 1].fld[iFld - 1]; byte[] buf; int i; while ((iFldType != -1) && (iFld <= Msgs.MAX_FLDS)) { //while more fields switch (iFldType) { //select the field type case (int)TTypedValue.TBaseType.ITYPE_INT4: { msg.dataPtr[ptr++] = (Byte)((uint)initArray[iFld - 1].intVal); msg.dataPtr[ptr++] = (Byte)(((uint)initArray[iFld - 1].intVal) >> 8); msg.dataPtr[ptr++] = (Byte)(((uint)initArray[iFld - 1].intVal) >> 16); msg.dataPtr[ptr++] = (Byte)(((uint)initArray[iFld - 1].intVal) >> 24); initArray[iFld - 1].fieldType = TTypedValue.TBaseType.ITYPE_EMPTY; initArray[iFld - 1].size = 0; } break; case (int)TTypedValue.TBaseType.ITYPE_BOOL: { buf = BitConverter.GetBytes(initArray[iFld - 1].boolVal); for (i = 0; i < TTypedValue.typeSize[(int)TTypedValue.TBaseType.ITYPE_BOOL]; i++) { msg.dataPtr[ptr++] = buf[i]; } initArray[iFld - 1].fieldType = TTypedValue.TBaseType.ITYPE_EMPTY; initArray[iFld - 1].size = 0; } break; case (int)TTypedValue.TBaseType.ITYPE_STR: { //copy the chars to the data block and set the DIM=x bytes int asize = initArray[iFld - 1].size; msg.dataPtr[ptr++] = (Byte)((uint)asize); msg.dataPtr[ptr++] = (Byte)(((uint)asize) >> 8); msg.dataPtr[ptr++] = (Byte)(((uint)asize) >> 16); msg.dataPtr[ptr++] = (Byte)(((uint)asize) >> 24); Array.Copy(ascii.GetBytes(initArray[iFld - 1].strVal), 0, msg.dataPtr, ptr, asize); ptr += asize; //for (int i = 0; i < asize; i++) // msg.dataPtr[ptr++] = initArray[iFld - 1].ptrVal[i]; initArray[iFld - 1].fieldType = TTypedValue.TBaseType.ITYPE_EMPTY; initArray[iFld - 1].size = 0; } break; case (int)TTypedValue.TBaseType.ITYPE_DEF: { //now copy the datablock from the typed value into the ptr Array.Copy(initArray[iFld - 1].ptrVal, 0, msg.dataPtr, ptr, initArray[iFld - 1].size); ptr += initArray[iFld - 1].size; initArray[iFld - 1].fieldType = TTypedValue.TBaseType.ITYPE_EMPTY; initArray[iFld - 1].size = 0; } break; } iFld++; //next field if (iFld <= Msgs.MAX_FLDS) //if there is another field { iFldType = msgSpec[msg.msgType - 1].fld[iFld - 1]; //get it's type } } newMsgBlockSize = 0; return(msg); }
//============================================================================ /// <summary> /// Overrides version in TBaseComponent /// </summary> /// <param name="msg">Incoming message.</param> //============================================================================ public override void handleMessage(TMsgHeader msg) { base.handleMessage(msg); //common messages }
//============================================================================ /// <summary> /// Sends a pause message to the sequencer /// </summary> /// <param name="msg"></param> //============================================================================ protected void pauseSimulation(TMsgHeader msg) { msg.to = sequencerID; //redirect to the sequencer sendMessage(msg); }
//============================================================================ /// <summary> /// Responds to the resume message by calling the sequencer /// </summary> /// <param name="msg">Incoming Resume message.</param> //============================================================================ protected override void handleResume(TMsgHeader msg) { resumeSimulation(); }
//============================================================================ /// <summary> /// Pauses the simulation msg back to the sender /// </summary> /// <param name="msg">Incoming Pause message.</param> //============================================================================ protected override void handlePause(TMsgHeader msg) { //sequencer sends a COMPLETE msg once received pauseSimulation(msg); //sends this msg off to the sequencer }