When using Guided Harnessing, the Port Registration functions are automatically generated in the AppIF.C file. The code can be modified if necessary. For manual harnessing, use this procedure:
To add new ports to your VMC or PIL Transform, use Port Registration functions. Add code the to your MSVC project as described here:
Port Registration Functions
Create a user-defined function named MxVRegisterPortDefinitions()in the AppIF.c file. This function is called during SUT loading. Use the functions described below to define ports on the VMC. For more examples, see the VMCPortDefinitions sample project.
Use this dataflow direction enumeration to specify the direction (input into the VMC or output from the VMC) of the ports: typedef enum { PortDataFlowInput, PortDataFlowOutput, } e_PortDataFlow;
|
Use these functions to define discrete ports, which access memory pointers to integral locations of memory. /* * Generic discrete value registration function * IMPORTANT NOTE: this function does not perform any bounds checking of the address, bit offset, and bit width, meaning that * overrunning the address desired in memory is very possible when defining ports using this function. * portName - the name of the port to export * direction - whether the port is an input or output * address - the address of the variable MxVDev will use to read/write data. * bitOffset - the number off bits from address that the data will be stored. * bitWidth - the number of bits in the memory that this variable takes. * isSigned - whether the data value should be treated as signed or unsigned when reading/writing. * minValue - the minimum value that this port will accept. * maxValue - the maximum value that this port will accept. * initialValue - the initial value of the port. */ void MxVRegisterPortDiscrete(const char portName[MM_MAX_NAME_LEN], e_PortDataFlow direction, void *address, size_t bitOffset, size_t bitWidth, mxBool isSigned, mxI64 minValue, mxI64 maxValue, mxI64 initialValue);
/* * Boolean value registration convenience function * note that the size of the underlying data type must be specified if this port will be used in an array so that offsets may be computed. * bitWidth must be 8/16/32/64 example: * char In0; * MxVRegisterPortBoolean("In0", PortDataFlowInput, &In0, sizeof(char), mxTrue); */ void MxVRegisterPortBoolean(const char portName[MM_MAX_NAME_LEN], e_PortDataFlow direction, void *address, size_t bitWidth, mxBool initialValue); /* * Discrete value registration convenience functions * These functions provide strongly typed versions of the MxVRegisterDiscretePort functions above as convenience. */ void MxVRegisterPortI8(const char portName[MM_MAX_NAME_LEN], e_PortDataFlow direction, mxI8 *address, mxI8 minValue, mxI8 maxValue, mxI8 initialValue); void MxVRegisterPortU8(const char portName[MM_MAX_NAME_LEN], e_PortDataFlow direction, mxU8 *address, mxU8 minValue, mxU8 maxValue, mxU8 initialValue); void MxVRegisterPortI16(const char portName[MM_MAX_NAME_LEN], e_PortDataFlow direction, mxI16 *address, mxI16 minValue, mxI16 maxValue, mxI16 initialValue); void MxVRegisterPortU16(const char portName[MM_MAX_NAME_LEN], e_PortDataFlow direction, mxU16 *address, mxU16 minValue, mxU16 maxValue, mxU16 initialValue); void MxVRegisterPortI32(const char portName[MM_MAX_NAME_LEN], e_PortDataFlow direction, mxI32 *address, mxI32 minValue, mxI32 maxValue, mxI32 initialValue); void MxVRegisterPortU32(const char portName[MM_MAX_NAME_LEN], e_PortDataFlow direction, mxU32 *address, mxU32 minValue, mxU32 maxValue, mxU32 initialValue); void MxVRegisterPortI64(const char portName[MM_MAX_NAME_LEN], e_PortDataFlow direction, mxI64 *address, mxI64 minValue, mxI64 maxValue, mxI64 initialValue); void MxVRegisterPortU64(const char portName[MM_MAX_NAME_LEN], e_PortDataFlow direction, mxU64 *address, mxU64 minValue, mxU64 maxValue, mxU64 initialValue); Examples To create a signed 64-bit discrete inport named "PRNDL" with a min of 1, a max of 5, and an initial value of 1, use either of these functions: •MxVRegisterPortDiscrete("PRNDL", PortDataFlowInput, &PRNDL, 0, 64, mxTrue, 1, 5, 1); •MxVRegisterPortI64("PRNDL", PortDataFlowInput, &PRNDL, 1, 5, 1); To create a Boolean port stored in bit 6 of variable DigIN: MxVRegisterPortDiscrete("Hazard_switch", PortDataFlowInput, &DigIN, 6, B01_BITS, mxFalse, 0, 1, 0); To associate an Enum set with the Signal, see Port Property Functions.
|
Use these Continuous floating point port definition functions to define ports that access IEEE floating point memory locations (32 bit or 64 bit). The bit width of the port must be wide enough to access an entire 32 bit or 64 bit location. /* Floating point value registration functions */ /* * Generic continuous value registration function * IMPORTANT NOTE: this function does not perform any bounds checking of the address, bit offset, meaning that * overrunning the address desired in memory is very possible when defining ports using this function. * portName - the name of the port to export * direction - whether the port is an input or output * address - the address of the variable MxVDev will use to read/write data. * bitOffset - the number off bits from address that the data will be stored. * bitWidth - the number of bits in the memory that this variable takes. For continuous signals, this is 32 or 64, depending on whether the * format is IEEE Float or IEEE double * minValue - the minimum value that this port will accept. * maxValue - the maximum value that this port will accept.
*/ void MxVRegisterPortContinuous(const char portName[MM_MAX_NAME_LEN], e_PortDataFlow direction, void *address, size_t bitOffset, size_t bitWidth, mxF64 minValue, mxF64 maxValue, mxF64 initialValue); /* * Continuous value registration convenience functions * These functions provide strongly typed versions of the MxVRegisterContinuousPort functions above as convenience. */ void MxVRegisterPortF32(const char portName[MM_MAX_NAME_LEN], e_PortDataFlow direction, mxF32 *address, mxF32 minValue, mxF32 maxValue, mxF32 initialValue); void MxVRegisterPortF64(const char portName[MM_MAX_NAME_LEN], e_PortDataFlow direction, mxF64 *address, mxF64 minValue, mxF64 maxValue, mxF64 initialValue); Example To create a 64-bit continuous inport named "TempC" with a min of zero, a max of 100, and an initial value of zero, use either of these functions: •MxVRegisterPortContinuous("TempC", PortDataFlowInput, &TempC, 0, 64, 0, 100, 0); •MxVRegisterPortF64("TempC", PortDataFlowInput, &TempC, 0, 100, 0); |
Message registration function. Assumption is that the port is a byte array. /* * Message registration function */ void MxVRegisterPortMessage(const char portName[MM_MAX_NAME_LEN], e_PortDataFlow direction, unsigned char *startAddress, size_t maximumByteLength, mxBool isVariableLength, mxBool sendOnChange);
Example MxVRegisterPortMessage("LCD Color Bitmap Buffer", PortDataFlowOutput, &LCD_Color_Bitmap_Buffer, 1920, mxFalse, mxTrue); |
/* * Task registration function * Takes an address to a user defined function that will be called when a task event occurs from MxVDev. The user defined function * is responsible for calling back to get parameter data, converting them to the real data type the function expects. On completion, * the user defined function is responsible for calling back to set any result data, which will be packed and sent back to MxVDev. The * Inbuf is an opaque pointers that are used for this purpose. * * For handlers that are called from the SUT, the task needs to call SetResultData with matching data * Handlers will have an input port to be triggered from MxVDev. Handlers will have a matching output port if they define either a result * data or have any parameters tagged as Output or Input/Output */ void MxVRegisterPortTask(const char portName[MM_MAX_NAME_LEN], void (*taskAddress)(void)); Examples To create a Task port, use this function: MxVRegisterPortTask("MyTask", &MyTask);
/* Register an asynchronous event task */ MxVRegisterPortTask("Event_20ms", NULL); MxVSetTaskParameterI64("Event_20ms", "CurrentSimTime", 0, LLONG_MAX, 0); MxVSetTaskParameterPointer("Event_20ms", "TickTimes", sizeof(tickTimes));
/* Register a parameterized task (in/out) */ MxVRegisterPortTask("sin", sin_task); /* Return value for the task */ MxVSetTaskParameterF64("sin", NULL, -1, 1, 0); MxVSetTaskParameterI64("sin", "time_ns", 0, LLONG_MAX, 0);
If you are using Task Signals with parameters, see Task Parameter Functions. |
![]() | Port Property Functions (Arrays, Enums, and Editor Type) |
Use these port property functions to set various port properties (array dimensions, enumerations, and editor type). Before properties are set, the port must be registered using one of the functions described above. /* * Array dimension functions * Calling this function will set the dimensions of the port portName to the specified dimensions. * Restrictions: An error will occur if the underlying port does not have a bit offset of zero or the bit width is not divisible by * 8, 16, 32, or 64 (the size of a fundamental data type). At run time, an individual element's location is computed as: * y * xDimension + x. * portName - the name of the port that will have the dimensions set. Note that the port must have previously been defined. * xDimension - the number of elements in the X dimension (the row width). * yDimension - the number of rows in the array. * Valid only on Numeric port types. */ void MxVSetPortDimensions(const char portName[MM_MAX_NAME_LEN], e_PortDataFlow direction, size_t xDimension, size_t yDimension);
/* * Set the Enumeration reference for a port * Attach an enumeration reference name to the port for MxVDev to read when scanning ports. */ void MxVSetPortEnumerationReference(const char portName[MM_MAX_NAME_LEN], e_PortDataFlow direction, const char enumerationReferenceName[MM_MAX_NAME_LEN]);
/* Handler function */ /* This is equivalent to the port description handler function. CurrentSigInd is set to the value passed to signalIndicator prior to the call. */ void MxVSetPortHandlerFunction(const char portName[MM_MAX_NAME_LEN], e_PortDataFlow direction, void(*handlerFunction)(void), void* signalIndicator);
|
Task parameter definition functions: Task parameters (and return values) can be defined using these functions. Note that the runtime task parameter set/get functions must be used to get the actual value that was passed along to the task. Only discrete, float, or fixed message (byte buffer) parameters are supported in the VMC. Task parameters are ordered in the order they are defined. To set the data type of the result of a task, use a NULL string for parameterName. /* * Set up the task parameters on a port. These are the data parameters that MxVDev will use externally. Conversions must be made by * the task handler to pass on to the actual user function. Parameters are uniquely identified by name. */ void MxVSetTaskParameterPointer(const char portName[MM_MAX_NAME_LEN], const char parameterName[MM_MAX_NAME_LEN], size_t byteLength); void MxVSetTaskParameterF64(const char portName[MM_MAX_NAME_LEN], const char parameterName[MM_MAX_NAME_LEN], mxF64 minValue, mxF64 maxValue, mxF64 initialValue); void MxVSetTaskParameterI64(const char portName[MM_MAX_NAME_LEN], const char parameterName[MM_MAX_NAME_LEN], mxI64 minValue, mxI64 maxValue, mxI64 initialValue);
Runtime task parameter retrieval functions: Because a task function is defined as a function neither returning nor passing data to the RTE, these functions allow the task port function that is called to retrieve any parameter data that was received along with the transition tick. The user may then set this information and use the data as appropriate. Note that this may not be used to retrieve a return value for a task, due to the fact that these are inputs to the task function. /* * Task handler data get functions. Used by the user defined and registered function to obtain the parameter data from the task transition * that MxVDev sends. Parameter name must be a registered value. */ void *MxVRetrieveTaskParameterDataPointer(const char portName[MM_MAX_NAME_LEN], const char parameterName[MM_MAX_NAME_LEN]); mxF64 MxVRetrieveTaskParameterDataF64(const char portName[MM_MAX_NAME_LEN], const char parameterName[MM_MAX_NAME_LEN]); mxI64 MxVRetrieveTaskParameterDataI64(const char portName[MM_MAX_NAME_LEN], const char parameterName[MM_MAX_NAME_LEN]);
Runtime task return value functions: Task functions may change the values of the task parameters and/or result during the function call. This is useful for setting results that are the product of a callback task of the SUT that sends feedback to MxVDev on a task. The parameter data is set, and an event is fired with the task return code and parameter data. To set the return value of the task, pass NULL to the parameterName field. /* * Task handler data set functions. Used by the user defined and registered function to set result data that will be sent via a transition to * MxVDev. Note that the SUT code may call a registered Task function to set results asynchronously if output parameters have been defined. */ void MxVSetTaskResultDataPointer(const char portName[MM_MAX_NAME_LEN], const char parameterName[MM_MAX_NAME_LEN], void *value, size_t numBytes); void MxVSetTaskResultDataF64(const char portName[MM_MAX_NAME_LEN], const char parameterName[MM_MAX_NAME_LEN], mxF64 value); void MxVSetTaskResultDataI64(const char portName[MM_MAX_NAME_LEN], const char parameterName[MM_MAX_NAME_LEN], mxI64 value);
|
Use this function to set the automatic tick period for a task port. The time is in nanoseconds.
void MxVSetTaskAutoTickPeriod(const char portName[MM_MAX_NAME_LEN], mxI64 timeSpan);
To use auto ticking with a manually harnessed VMC, use these Port Registration functions in the appif_register.h file: This function creates the SUT Tick port: MxVRegisterPortTask("SUT Tick", &SUT_Tick); This function sets the auto tick period. In the example below the tick period is 50 ms: MxVSetTaskAutoTickPeriod("SUT Tick", 50000000);
If you are using Guided Harnessing, use the Call Automatically mode on the SUT Tick Signal. See Guided Harnessing. |