File: rt_logging.c1 /* 2 * 3 * Copyright 1994-2012 The MathWorks, Inc. 4 * 5 * File: rt_logging.c 6 * 7 * Abstract: 8 * Real-Time Workshop data logging routines using circular buffers of 9 * fixed size. The buffers are allocated at start, filled in at each 10 * major time step and finally written to a MAT-file at the end of the 11 * simulation. 12 * 13 * This file handles redefining the following standard MathWorks types 14 * (see tmwtypes.h): 15 * [u]int8_T to be int32_T (logged as Matlab [u]int32) 16 * [u]int16_T to be int32_T (logged as Matlab [u]int32) 17 * real_T to be real32_T (logged as Matlab single) 18 * 19 */ 20 21 #define PUBLIC 22 #define BEGIN_PUBLIC 23 #define END_PUBLIC 24 25 #include <stdlib.h> 26 #include <string.h> 27 #include <stdio.h> 28 #include <math.h> 29 30 BEGIN_PUBLIC 31 #if !defined(MAT_FILE) || (defined(MAT_FILE) && MAT_FILE == 1) 32 33 #include <stddef.h> /* size_t */ 34 #include "rtwtypes.h" 35 #include "rt_mxclassid.h" 36 #include "rtw_matlogging.h" 37 38 #ifndef TMW_NAME_LENGTH_MAX 39 #define TMW_NAME_LENGTH_MAX 64 40 #endif 41 #define mxMAXNAM TMW_NAME_LENGTH_MAX /* maximum name length */ 42 43 /*=========* 44 * Defines * 45 *=========*/ 46 47 /* 48 * Logging related functions and data structures 49 */ 50 typedef double MatReal; /* "real" data type used in model.mat */ 51 typedef struct LogVar_Tag LogVar; 52 typedef struct StructLogVar_Tag StructLogVar; 53 54 typedef struct MatrixData_Tag { 55 char_T name[mxMAXNAM]; /* Name of the variable */ 56 int_T nRows; /* number of rows */ 57 int_T nCols; /* number of columns */ 58 int_T nDims; /* number of dimensions */ 59 int_T _dims[2]; /* most cases, dimensions are 2 */ 60 int_T *dims; /* dimensions of the log variable we 61 write to at each simulation time step. 62 E.g: (1) Non-frame data - 63 Signal dimension = [2 X 3] 64 numDims = 2 65 dims[0] = 2, dims[1] = 3 66 (2) Frame data - 67 Signal dimension = [2 X 3] 68 numDims = 1 69 dims[0] = 3 */ 70 void *re; /* pointer to real part of the data */ 71 void *im; /* pointer to imaginary part, if complex */ 72 DTypeId dTypeID; /* data type id */ 73 size_t elSize; /* element size in bytes */ 74 75 RTWLogDataTypeConvert dataTypeConvertInfo; 76 77 mxClassID mxID; /* mxId corresponding to this dTypeID */ 78 uint32_T logical; /* is this a logical array ? */ 79 uint32_T complex; /* is this a complex matrix? */ 80 uint32_T frameData; /* is this data frame based? */ 81 uint32_T frameSize; /* is this data frame based? */ 82 } MatrixData; 83 84 typedef struct ValDimsData_Tag { 85 char_T name[mxMAXNAM]; /* Name of the variable */ 86 int_T nRows; /* number of rows */ 87 int_T nCols; /* number of columns */ 88 void **currSigDims; /* dimensions of current output */ 89 int_T *currSigDimsSize; /* size in bytes of current sig dims */ 90 real_T *dimsData; /* pointer to the value of dimension */ 91 } ValDimsData; 92 93 struct LogVar_Tag { 94 MatrixData data; /* Container for name, data etc., */ 95 ValDimsData *valDims; /* field of valueDimensions 96 1. If all logging signals are fixed-size, 97 then we set this field to NULL; 98 2. If any logging signal is variable-size, 99 then this field will be needed: 100 1) For fixed-size signal, this field is 101 an empty matrix; 102 2) Otherwise, it contains the dimension 103 information of the logging signal. 104 */ 105 int_T rowIdx; /* current row index */ 106 int_T wrapped; /* number of times the circular buffer 107 * has wrapped around */ 108 int_T nDataPoints; /* total number of data points logged */ 109 int_T usingDefaultBufSize; /* used to print a message at end */ 110 int_T okayToRealloc; /* reallocate during sim? */ 111 int_T decimation; /* decimation factor */ 112 int_T numHits; /* decimation hit count */ 113 114 int_T *coords; 115 int_T *strides; 116 int_T *currStrides; /* coords, strides and currStrides will be 117 needed when logging variable-size 118 signal to calculate whether the 119 currently logging value is in the range. 120 If the current signal is fixed-size, 121 these pointers will be set to NULLs; 122 otherwise, we allocate memory for them. 123 (the size will be nDims in this case) 124 */ 125 126 LogVar *next; 127 }; 128 129 typedef struct SignalsStruct_Tag { 130 int_T numActiveFields; /* number of active fields */ 131 const char_T *fieldNames; 132 int_T numSignals; 133 LogVar *values; 134 MatrixData *dimensions; 135 MatrixData *labels; 136 MatrixData *plotStyles; 137 MatrixData *titles; 138 MatrixData *blockNames; 139 MatrixData *stateNames; 140 MatrixData *crossMdlRef; 141 142 boolean_T logValueDimensions; /* If there's any variable-size signal 143 we also should log 'valueDimensions' 144 field */ 145 boolean_T *isVarDims; /* is this signal a variable-size signal? */ 146 } SignalsStruct; 147 148 struct StructLogVar_Tag { 149 char_T name[mxMAXNAM]; /* Name of the ML Struct variable */ 150 int_T numActiveFields; /* number of active fields */ 151 boolean_T logTime; 152 void *time; 153 SignalsStruct signals; 154 MatrixData *blockName; 155 156 StructLogVar *next; 157 }; 158 159 #define matUNKNOWN 0 160 #define matINT8 1 161 #define matUINT8 2 162 #define matINT16 3 163 #define matUINT16 4 164 #define matINT32 5 165 #define matUINT32 6 166 #define matFLOAT 7 167 #define matDOUBLE 9 168 #define matINT64 12 169 #define matUINT64 13 170 #define matMATRIX 14 171 172 /* status of logging "valueDimensions" field */ 173 /* 174 NO_LOGVALDIMS: 175 No need to log valueDimensions: 176 All signals are fixed-sized. 177 178 LOGVALDIMS_EMPTYMX: 179 Signals with mixed dimension modes, 180 and the signal logged currently 181 is fixed-sized. So set valueDimensions 182 field to an empty matrix. 183 184 LOGVALDIMS_VARDIMS: 185 Signal logged currently is variable-sized. 186 */ 187 typedef enum { 188 NO_LOGVALDIMS, 189 LOGVALDIMS_EMPTYMX, 190 LOGVALDIMS_VARDIMS 191 } LogValDimsStat; 192 193 END_PUBLIC 194 195 #define matLOGICAL_BIT 0x200 196 #define matCOMPLEX_BIT 0x800 197 198 #define matKEY 0x4D49 199 #define matVERSION 0x0100 200 #define matVERSION_INFO_OFFSET 124L 201 202 #define matINT64_ALIGN(e) ( ( ((unsigned)(e))+7 ) & (~7) ) 203 #define matTAG_SIZE (sizeof(int32_T) << 1) 204 205 #ifndef DEFAULT_BUFFER_SIZE 206 #define DEFAULT_BUFFER_SIZE 1024 /* used if maxRows=0 and Tfinal=0.0 */ 207 #endif 208 209 #define FREE(m) if (m != NULL) free(m) 210 211 /*==========* 212 * typedefs * 213 *==========*/ 214 215 typedef struct LogInfo_Tag { 216 LogVar *t; /* Time log variable */ 217 void *x; /* State log variable */ 218 void *sl; /* SigLog log variable */ 219 int_T ny; /* Length of "y" log variables */ 220 void **y; /* Output log vars */ 221 void *xFinal; /* Final state log variable */ 222 223 LogVar *logVarsList; /* Linked list of all LogVars */ 224 StructLogVar *structLogVarsList; /* Linked list of all StructLogVars */ 225 226 boolean_T haveLogVars; /* Are logging one or more vars? */ 227 } LogInfo; 228 229 typedef struct MatItem_tag { 230 int32_T type; 231 int32_T nbytes; 232 const void *data; 233 } MatItem; 234 235 typedef enum { 236 DATA_ITEM, 237 MATRIX_ITEM, 238 STRUCT_LOG_VAR_ITEM, 239 SIGNALS_STRUCT_ITEM 240 } ItemDataKind; 241 242 /*===========* 243 * Constants * 244 *===========*/ 245 246 static const char_T rtMemAllocError[] = "Memory allocation error"; 247 248 #define ZEROS32 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" 249 250 #if mxMAXNAM==32 251 252 #define ZERO_PAD 253 254 #elif mxMAXNAM==64 255 256 #define ZERO_PAD ZEROS32 257 258 #elif mxMAXNAM==128 259 260 #define ZERO_PAD ZEROS32 ZEROS32 ZEROS32 261 262 #else 263 264 #error "Cannot Handle mxMAXNAM other than 32,64, and 128" 265 266 #endif 267 /* field names: for variable-size signal logging */ 268 static const char_T rtStructLogVarFieldNames[] = 269 "time\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD 270 "signals\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD 271 "blockName\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD; 272 static const char_T rtLocalLoggingSignalsStructFieldNames[] = 273 "values\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD 274 "valueDimensions\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD 275 "dimensions\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD 276 "label\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD 277 "title\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD 278 "plotStyle\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD; 279 static const char_T rtGlobalLoggingSignalsStructFieldNames[] = 280 "values\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD 281 "valueDimensions\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD 282 "dimensions\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD 283 "label\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD 284 "blockName\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD 285 "stateName\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD 286 "inReferencedModel\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD; 287 #define TIME_FIELD_NAME (rtStructLogVarFieldNames[0*mxMAXNAM]) 288 #define SIGNALS_FIELD_NAME (rtStructLogVarFieldNames[1*mxMAXNAM]) 289 #define BLOCKNAME_FIELD_NAME (rtStructLogVarFieldNames[2*mxMAXNAM]) 290 291 #define VALUES_FIELD_NAME (rtLocalLoggingSignalsStructFieldNames[0*mxMAXNAM]) 292 #define VALUEDIMENSIONS_FIELD_NAME (rtLocalLoggingSignalsStructFieldNames[1*mxMAXNAM]) 293 #define DIMENSION_FIELD_NAME (rtLocalLoggingSignalsStructFieldNames[2*mxMAXNAM]) 294 #define LABEL_FIELD_NAME (rtLocalLoggingSignalsStructFieldNames[3*mxMAXNAM]) 295 #define TITLE_FIELD_NAME (rtLocalLoggingSignalsStructFieldNames[4*mxMAXNAM]) 296 #define PLOTSTYLE_FIELD_NAME (rtLocalLoggingSignalsStructFieldNames[5*mxMAXNAM]) 297 298 #define STATENAME_FIELD_NAME (rtGlobalLoggingSignalsStructFieldNames[5*mxMAXNAM]) 299 #define CROSS_MDL_REF_FIELD_NAME (rtGlobalLoggingSignalsStructFieldNames[6*mxMAXNAM]) 300 301 /* field names: for fixed-size signal logging */ 302 static const char_T rtLocalLoggingSignalsStructFieldNames_noValDims[] = 303 "values\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD 304 "dimensions\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD 305 "label\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD 306 "title\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD 307 "plotStyle\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD; 308 static const char_T rtGlobalLoggingSignalsStructFieldNames_noValDims[] = 309 "values\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD 310 "dimensions\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD 311 "label\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD 312 "blockName\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD 313 "stateName\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD 314 "inReferencedModel\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD; 315 316 extern real_T rtInf; /* declared by rt_nonfinite.c */ 317 extern real_T rtNaN; 318 extern real32_T rtNaNF; 319 320 /*================* 321 * Local routines * 322 *================*/ 323 324 /* Forward declaration */ 325 LogVar *rt_CreateLogVarWithConvert(RTWLogInfo *li, 326 const real_T startTime, 327 const real_T finalTime, 328 const real_T inStepSize, 329 const char_T **errStatus, 330 const char_T *varName, 331 BuiltInDTypeId inpDataTypeID, 332 const RTWLogDataTypeConvert *pDataTypeConvertInfo, 333 int_T logical, 334 int_T complex, 335 int_T frameData, 336 int_T nCols, 337 int_T nDims, 338 const int_T *dims, 339 LogValDimsStat logVarDimsStat, 340 void **currSigDims, 341 int_T *currSigDimsSize, 342 int_T maxRows, 343 int_T decimation, 344 real_T sampleTime, 345 int_T appendToLogVarsList); 346 347 348 /* Function: rt_GetSizeofDataType ============================================== 349 * Abstract: 350 * Get the element size in bytes given the data type id. 351 */ 352 static size_t rt_GetSizeofDataType(BuiltInDTypeId dTypeID) 353 { 354 size_t elSz = 0; /* unknown */ 355 356 switch (dTypeID) { 357 case SS_DOUBLE: 358 elSz = sizeof(real_T); 359 break; 360 case SS_SINGLE: 361 elSz = sizeof(real32_T); 362 break; 363 case SS_INT8: 364 elSz = sizeof(int8_T); 365 break; 366 case SS_UINT8: 367 elSz = sizeof(uint8_T); 368 break; 369 case SS_INT16: 370 elSz = sizeof(int16_T); 371 break; 372 case SS_UINT16: 373 elSz = sizeof(uint16_T); 374 break; 375 case SS_INT32: 376 elSz = sizeof(int32_T); 377 break; 378 case SS_UINT32: 379 elSz = sizeof(uint32_T); 380 break; 381 case SS_BOOLEAN: 382 elSz = sizeof(boolean_T); 383 break; 384 } 385 return(elSz); 386 387 } /* end rt_GetSizeofDataType */ 388 389 390 /* Function: rt_GetSizeofComplexType =========================================== 391 * Abstract: 392 * Get the element size in bytes given the data type id. 393 */ 394 static size_t rt_GetSizeofComplexType(BuiltInDTypeId dTypeID) 395 { 396 size_t elSz = 2*rt_GetSizeofDataType(dTypeID); 397 398 switch (dTypeID) { 399 case SS_DOUBLE: 400 #ifdef CREAL_T 401 elSz = sizeof(creal_T); 402 #endif 403 break; 404 case SS_SINGLE: 405 #ifdef CREAL_T 406 elSz = sizeof(creal32_T); 407 #endif 408 break; 409 case SS_INT8: 410 #ifdef _CINT8_T 411 elSz = sizeof(cint8_T); 412 #endif 413 break; 414 case SS_UINT8: 415 #ifdef _CUINT8_T 416 elSz = sizeof(cuint8_T); 417 #endif 418 break; 419 case SS_INT16: 420 #ifdef _CINT16_T 421 elSz = sizeof(cint16_T); 422 #endif 423 break; 424 case SS_UINT16: 425 #ifdef _CUINT16_T 426 elSz = sizeof(cuint16_T); 427 #endif 428 break; 429 case SS_INT32: 430 #ifdef _CINT32_T 431 elSz = sizeof(cint32_T); 432 #endif 433 break; 434 case SS_UINT32: 435 #ifdef _CUINT32_T 436 elSz = sizeof(cuint32_T); 437 #endif 438 break; 439 case SS_BOOLEAN: 440 elSz = sizeof(boolean_T); 441 break; 442 } 443 444 return(elSz); 445 446 } /* end rt_GetSizeofComplexType */ 447 448 449 /* Function: rt_GetDataTypeConvertInfo ========================================= 450 * Abstract: 451 * Directly copy if pointer to structure is non-NULL, otherwise set to 452 * default. 453 */ 454 static RTWLogDataTypeConvert rt_GetDataTypeConvertInfo( 455 const RTWLogDataTypeConvert *pDataTypeConvertInfo, 456 BuiltInDTypeId dTypeID 457 ) 458 { 459 RTWLogDataTypeConvert dataTypeConvertInfoCopy; 460 461 if (pDataTypeConvertInfo == NULL) { 462 dataTypeConvertInfoCopy.conversionNeeded = 0; 463 dataTypeConvertInfoCopy.dataTypeIdLoggingTo = dTypeID; 464 dataTypeConvertInfoCopy.dataTypeIdOriginal = (DTypeId)dTypeID; 465 dataTypeConvertInfoCopy.bitsPerChunk = 0; 466 dataTypeConvertInfoCopy.numOfChunk = 0; 467 dataTypeConvertInfoCopy.isSigned = 0; 468 dataTypeConvertInfoCopy.fracSlope = 1.0; 469 dataTypeConvertInfoCopy.fixedExp = 0; 470 dataTypeConvertInfoCopy.bias = 0.0; 471 } else { 472 dataTypeConvertInfoCopy = *pDataTypeConvertInfo; 473 } 474 475 return dataTypeConvertInfoCopy; 476 477 } /* end rt_GetDataTypeConvertInfo */ 478 479 480 /* Function: rt_GetDblValueFromOverSizedData =================================== 481 * Abstract: 482 */ 483 static double rt_GetDblValueFromOverSizedData( 484 const void *pVoid, 485 int bitsPerChunk, 486 int numOfChunk, 487 unsigned int isSigned, 488 double fracSlope, 489 int fixedExp, 490 double bias) 491 { 492 double retValue = 0; 493 494 double *dblValue = (double *) calloc(numOfChunk, sizeof(double)); 495 496 int i; 497 double isSignedNeg; 498 499 if(isSigned) { 500 const chunk_T *pData = (const chunk_T *) (pVoid); 501 for (i = 0; i <numOfChunk; i++) { 502 dblValue[i] = (double)(pData[i]); 503 } 504 } else { 505 const uchunk_T *pData = (const uchunk_T *) (pVoid); 506 for (i = 0; i <numOfChunk; i++) { 507 dblValue[i] = (double)(pData[i]); 508 } 509 } 510 511 /* 512 Assuming multi chunks b_n ... b_2 b_1 b_0, and the length of each chunk is N. 513 Suppose b_i is the i-th chunk's value. 514 Then for unsigned data or data with one chunk: we have 515 retValue = b_n * 2^(n*N) + ... + b_1 * 2^N + b_0 * 2^0; 516 But for signed data, we have 517 retValue = b_n * 2^(n*N) + ... + b_1 * 2^N + b_0 * 2^0+ (b_0<0) * 2^N + 518 ... (b_(n-1) <0) * 2^(n*N) 519 = (b_n + (b_(n-1)<0)) * 2^(n*N) +... + (b_1 + (b_0<0)) * 2^N + b_0 * 2^0; 520 Together: 521 retValue = 522 (b_n + isSigned * (b_(n-1)<0)) * 2^(n*N) +... + (b_1 + isSigned * (b_0<0)) * 2^N + b_0 * 2^0; 523 */ 524 525 retValue = dblValue[numOfChunk - 1]; 526 527 for(i = numOfChunk - 1; i > 0; i--) { 528 isSignedNeg = dblValue[i - 1] < 0 ? (double)isSigned : 0; 529 retValue = retValue + isSignedNeg; 530 531 retValue = ldexp(retValue, bitsPerChunk)+ dblValue[i-1]; 532 } 533 retValue = ldexp( fracSlope * retValue, fixedExp ) + bias; 534 535 FREE(dblValue); 536 return (retValue); 537 538 } /* end rt_GetDblValueFromOverSizedData */ 539 540 541 /* Function: rt_GetNonBoolMxIdFromDTypeId ====================================== 542 * Abstract: 543 * Get the mx???_CLASS given the simulink builtin data type id. 544 */ 545 mxClassID rt_GetNonBoolMxIdFromDTypeId(BuiltInDTypeId dTypeID) 546 { 547 mxClassID mxID; 548 549 switch (dTypeID) { 550 case SS_DOUBLE: 551 mxID = (sizeof(real_T)==4? mxSINGLE_CLASS: mxDOUBLE_CLASS); 552 break; 553 case SS_SINGLE: 554 mxID = mxSINGLE_CLASS; 555 break; 556 case SS_INT8: 557 mxID = (sizeof(int8_T)==4? mxINT32_CLASS: mxINT8_CLASS); 558 break; 559 case SS_UINT8: 560 mxID = (sizeof(uint8_T)==4? mxUINT32_CLASS: mxUINT8_CLASS); 561 break; 562 case SS_INT16: 563 mxID = (sizeof(int16_T)==4? mxINT32_CLASS: mxINT16_CLASS); 564 break; 565 case SS_UINT16: 566 mxID = (sizeof(uint16_T)==4? mxUINT32_CLASS: mxUINT16_CLASS); 567 break; 568 case SS_INT32: 569 mxID = mxINT32_CLASS; 570 break; 571 case SS_UINT32: 572 mxID = mxUINT32_CLASS; 573 break; 574 /*case SS_BOOLEAN: 575 mxID = (sizeof(boolean_T)==4? mxUINT32_CLASS: mxLOGICAL_CLASS); 576 break;*/ 577 default: 578 mxID = mxUNKNOWN_CLASS; 579 break; 580 } 581 582 return(mxID); 583 584 } /* end rt_GetNonBoolMxIdFromDTypeId */ 585 586 587 BEGIN_PUBLIC 588 #ifdef __cplusplus 589 extern "C" { 590 #endif 591 END_PUBLIC 592 593 /* Function: rt_GetMxIdFromDTypeIdForRSim ====================================== 594 * Abstract: 595 * Get the mx???_CLASS given the simulink builtin data type id. 596 */ 597 PUBLIC mxClassID rt_GetMxIdFromDTypeIdForRSim(BuiltInDTypeId dTypeID) 598 { 599 mxClassID mxID; 600 601 if (dTypeID == SS_BOOLEAN) { 602 mxID = (sizeof(boolean_T)==4? mxUINT32_CLASS: mxLOGICAL_CLASS); 603 } else { 604 mxID = rt_GetNonBoolMxIdFromDTypeId(dTypeID); 605 } 606 607 return(mxID); 608 609 } /* end rt_GetMxIdFromDTypeIdForRSim */ 610 611 BEGIN_PUBLIC 612 #ifdef __cplusplus 613 } 614 #endif 615 END_PUBLIC 616 617 618 BEGIN_PUBLIC 619 #ifdef __cplusplus 620 extern "C" { 621 #endif 622 END_PUBLIC 623 624 /* Function: rt_GetMxIdFromDTypeId ============================================= 625 * Abstract: 626 * Get the mx???_CLASS given the simulink builtin data type id. 627 */ 628 PUBLIC mxClassID rt_GetMxIdFromDTypeId(BuiltInDTypeId dTypeID) 629 { 630 mxClassID mxID; 631 632 if (dTypeID == SS_BOOLEAN) { 633 mxID = (sizeof(boolean_T)==4? mxUINT32_CLASS: mxUINT8_CLASS); 634 } else { 635 mxID = rt_GetNonBoolMxIdFromDTypeId(dTypeID); 636 } 637 return(mxID); 638 639 } /* end rt_GetMxIdFromDTypeId */ 640 641 BEGIN_PUBLIC 642 #ifdef __cplusplus 643 } 644 #endif 645 END_PUBLIC 646 647 648 /* Function: rt_GetMatIdFromMxId =============================================== 649 * Abstract: 650 * Get the MatId given the mxClassID. 651 */ 652 static int_T rt_GetMatIdFromMxId(mxClassID mxID) 653 { 654 int_T matID; 655 656 switch (mxID) { 657 case mxCELL_CLASS: 658 case mxSTRUCT_CLASS: 659 case mxOBJECT_CLASS: 660 matID = -1; 661 break; 662 case mxCHAR_CLASS: 663 matID = matUINT16; 664 break; 665 case mxDOUBLE_CLASS: 666 matID = matDOUBLE; 667 break; 668 case mxSINGLE_CLASS: 669 matID = matFLOAT; 670 break; 671 case mxINT8_CLASS: 672 matID = matINT8; 673 break; 674 case mxUINT8_CLASS: 675 matID = matUINT8; 676 break; 677 case mxINT16_CLASS: 678 matID = matINT16; 679 break; 680 case mxUINT16_CLASS: 681 matID = matUINT16; 682 break; 683 case mxINT32_CLASS: 684 matID = matINT32; 685 break; 686 case mxUINT32_CLASS: 687 matID = matUINT32; 688 break; 689 case mxINT64_CLASS: 690 matID = matINT64; 691 break; 692 case mxUINT64_CLASS: 693 matID = matUINT64; 694 break; 695 default: 696 matID = matUNKNOWN; 697 break; 698 } 699 return(matID); 700 701 } /* end rt_GetMatIdFromMxId */ 702 703 704 /* Forward declaration */ 705 static int_T rt_WriteItemToMatFile(FILE *fp, 706 MatItem *pItem, 707 ItemDataKind dataKind); 708 709 710 /* Function: rt_ProcessMatItem ================================================= 711 * Abstract: 712 * This routine along with rt_WriteItemToMatFile() write out a specified 713 * mat-item the .mat file. Note that if the input argument 714 * cmd == 0, then this function just calculates the size of the item. 715 * cmd <> 0, this function writes the mat-item to the file. 716 * Return values is 717 * -1 : coding/logic error 718 * 0 : upon success 719 * > 0 : upon write failure (1) 720 */ 721 static int_T rt_ProcessMatItem(FILE *fp, 722 MatItem *pItem, 723 ItemDataKind itemKind, 724 int_T cmd) 725 { 726 mxClassID mxID = mxUNKNOWN_CLASS; 727 uint32_T arrayFlags[2] = {0, 0}; 728 int32_T *dims = NULL; 729 int32_T _dims[3] = {0, 0, 0}; 730 int32_T nDims = 2; 731 int32_T nBytesInItem = 0; 732 const char_T *itemName; 733 MatItem item; 734 int_T retStat = 0; 735 736 switch (itemKind) { 737 case DATA_ITEM: { 738 (void)fprintf(stderr,"Unexpected itemKind = DATA_ITEM in " 739 "rt_ProcessMatItem @A\n"); 740 retStat = -1; 741 goto EXIT_POINT; 742 } 743 case MATRIX_ITEM: { 744 const MatrixData *var = (const MatrixData *) pItem->data; 745 746 mxID = var->mxID; 747 arrayFlags[0] = mxID; 748 arrayFlags[0] |= var->logical; 749 arrayFlags[0] |= var->complex; 750 if (var->nDims < 2) { 751 dims = _dims; 752 dims[0] = var->nRows; 753 dims[1] = var->nCols; 754 nDims = 2; 755 } else if (var->nDims >= 2) { 756 int32_T k; 757 dims = (int32_T*)malloc(sizeof(int32_T)*(var->nDims+1)); 758 for (k = 0; k < var->nDims; k++) { 759 dims[k] = var->dims[k]; 760 } 761 dims[var->nDims] = var->nRows; 762 nDims = var->nDims + 1; 763 } 764 itemName = var->name; 765 break; 766 } 767 case STRUCT_LOG_VAR_ITEM: { 768 const StructLogVar *var = (const StructLogVar *) pItem->data; 769 770 mxID = mxSTRUCT_CLASS; 771 arrayFlags[0] = mxID; 772 dims = _dims; 773 dims[0] = 1; 774 dims[1] = 1; 775 itemName = var->name; 776 break; 777 } 778 case SIGNALS_STRUCT_ITEM: { 779 const SignalsStruct *var = (const SignalsStruct *) pItem->data; 780 781 mxID = mxSTRUCT_CLASS; 782 arrayFlags[0] = mxID; 783 dims = _dims; 784 dims[0] = 1; 785 dims[1] = var->numSignals; 786 itemName = &SIGNALS_FIELD_NAME; 787 break; 788 } 789 default: 790 (void)fprintf(stderr,"Unexpected itemKind=%d in rt_ProcessMatItem @B\n", 791 itemKind); 792 retStat = -1; 793 goto EXIT_POINT; 794 } 795 796 /* array flags */ 797 item.nbytes = 2*sizeof(uint32_T); 798 if (cmd) { 799 item.type = matUINT32; 800 item.data = arrayFlags; 801 if (rt_WriteItemToMatFile(fp,&item, DATA_ITEM)) { 802 retStat = 1; 803 goto EXIT_POINT; 804 } 805 } else { 806 /*LINTED E_CAST_INT_TO_SMALL_INT*/ 807 nBytesInItem += matINT64_ALIGN(matTAG_SIZE + item.nbytes); 808 } 809 /* dimensions */ 810 /*LINTED E_ASSIGN_INT_TO_SMALL_INT*/ 811 item.nbytes = nDims*sizeof(int32_T); 812 if (cmd) { 813 item.type = matINT32; 814 item.data = dims; 815 if (rt_WriteItemToMatFile(fp,&item, DATA_ITEM)) { 816 retStat = 1; 817 goto EXIT_POINT; 818 } 819 } else { 820 /*LINTED E_CAST_INT_TO_SMALL_INT*/ 821 nBytesInItem += matINT64_ALIGN(matTAG_SIZE + item.nbytes); 822 } 823 /* name */ 824 item.nbytes = (int32_T)strlen(itemName); 825 if (cmd) { 826 item.type = matINT8; 827 item.data = (const char_T*) itemName; 828 if (rt_WriteItemToMatFile(fp,&item, DATA_ITEM)) { 829 retStat = 1; 830 goto EXIT_POINT; 831 } 832 } else { 833 nBytesInItem += (item.nbytes <= 4) ? /*LINTED E_CAST_INT_TO_SMALL_INT*/ 834 matTAG_SIZE : matINT64_ALIGN(matTAG_SIZE + item.nbytes); 835 } 836 837 if (itemKind == MATRIX_ITEM) { 838 const MatrixData *var = (const MatrixData*) pItem->data; 839 int_T matID = rt_GetMatIdFromMxId(mxID); 840 size_t elSize = var->elSize; 841 842 /* data */ 843 item.nbytes = (int32_T)(var->nRows * var->nCols * elSize); 844 if (cmd) { 845 item.type = matID; 846 item.data = var->re; 847 if (rt_WriteItemToMatFile(fp, &item, DATA_ITEM)) { 848 retStat = 1; 849 goto EXIT_POINT; 850 } 851 } else { 852 nBytesInItem += (item.nbytes <= 4) ? /*LINTED*/ 853 matTAG_SIZE : matINT64_ALIGN(matTAG_SIZE + item.nbytes); 854 } 855 /* imaginary part */ 856 if (var->complex) { 857 item.nbytes = (int32_T)(var->nRows * var->nCols * elSize); 858 if (cmd) { 859 item.type = matID; 860 item.data = var->im; 861 if (rt_WriteItemToMatFile(fp, &item, DATA_ITEM)) { 862 retStat = 1; 863 goto EXIT_POINT; 864 } 865 } else { 866 nBytesInItem += (item.nbytes <= 4) ? /*LINTED*/ 867 matTAG_SIZE : matINT64_ALIGN(matTAG_SIZE + item.nbytes); 868 } 869 } 870 } else { /* some type of structure item */ 871 const char_T *fieldNames; 872 int_T sizeofFieldNames; 873 874 /* field names */ 875 switch (itemKind) { 876 case STRUCT_LOG_VAR_ITEM: { 877 const StructLogVar *var = (const StructLogVar *) pItem->data; 878 fieldNames = rtStructLogVarFieldNames; 879 sizeofFieldNames = var->numActiveFields * mxMAXNAM; 880 break; 881 } 882 case SIGNALS_STRUCT_ITEM: { 883 const SignalsStruct *var = (const SignalsStruct *) pItem->data; 884 fieldNames = var->fieldNames; 885 sizeofFieldNames = var->numActiveFields * mxMAXNAM; 886 break; 887 } 888 default: 889 (void)fprintf(stderr, "Unexpected itemKind=%d in " 890 "rt_ProcessMatItem @C\n", itemKind); 891 retStat = -1; 892 goto EXIT_POINT; 893 } 894 895 /* write field names */ 896 if (cmd) { 897 int32_T tmpInt = mxMAXNAM; 898 899 item.nbytes = sizeof(int32_T); 900 item.type = matINT32; 901 item.data = &tmpInt; 902 if (rt_WriteItemToMatFile(fp,&item, DATA_ITEM)) { 903 retStat = 1; 904 goto EXIT_POINT; 905 } 906 907 item.nbytes = sizeofFieldNames; 908 item.type = matINT8; 909 item.data = (const char_T*) fieldNames; 910 if (rt_WriteItemToMatFile(fp,&item, DATA_ITEM)) { 911 retStat = 1; 912 goto EXIT_POINT; 913 } 914 } else { 915 /*LINTED E_CAST_INT_TO_SMALL_INT*/ 916 nBytesInItem += matINT64_ALIGN( matTAG_SIZE + matTAG_SIZE + 917 sizeofFieldNames ); 918 } 919 920 /* process each field of the structure */ 921 switch (itemKind) { 922 case STRUCT_LOG_VAR_ITEM: { 923 const StructLogVar *var = pItem->data; 924 925 /* time */ 926 { 927 const void *data = var->time; 928 929 if (var->logTime) { /* time is a LogVar, get the MatrixData */ 930 data = &(((const LogVar*) (var->time))->data); 931 } 932 933 item.type = matMATRIX; 934 item.data = data; 935 if (cmd) { 936 if (rt_WriteItemToMatFile(fp,&item,MATRIX_ITEM)){ 937 retStat = 1; 938 goto EXIT_POINT; 939 } 940 } else { 941 if (rt_ProcessMatItem(fp, &item, MATRIX_ITEM,0)){ 942 retStat = 1; 943 goto EXIT_POINT; 944 } 945 nBytesInItem += item.nbytes + matTAG_SIZE; 946 } 947 } 948 949 /* signals */ 950 item.type = matMATRIX; 951 item.data = &(var->signals); 952 if (cmd) { 953 if (rt_WriteItemToMatFile(fp,&item,SIGNALS_STRUCT_ITEM)) { 954 retStat = 1; 955 goto EXIT_POINT; 956 } 957 } else { 958 if (rt_ProcessMatItem(fp, &item, SIGNALS_STRUCT_ITEM,0)) { 959 retStat = 1; 960 goto EXIT_POINT; 961 } 962 nBytesInItem += item.nbytes + matTAG_SIZE; 963 } 964 965 /* block name */ 966 if (var->blockName != NULL) { 967 item.type = matMATRIX; 968 item.data = var->blockName; 969 if (cmd) { 970 if (rt_WriteItemToMatFile(fp, &item, MATRIX_ITEM)) { 971 retStat = 1; 972 goto EXIT_POINT; 973 } 974 } else { 975 if (rt_ProcessMatItem(fp, &item, MATRIX_ITEM, 0)) { 976 retStat = 1; 977 goto EXIT_POINT; 978 } 979 nBytesInItem += item.nbytes + matTAG_SIZE; 980 } 981 } 982 break; 983 } 984 case SIGNALS_STRUCT_ITEM: { 985 const SignalsStruct *var = pItem->data; 986 const LogVar *values = var->values; 987 const MatrixData *dimensions = var->dimensions; 988 const MatrixData *labels = var->labels; 989 const MatrixData *plotStyles = var->plotStyles; 990 const MatrixData *titles = var->titles; 991 const MatrixData *blockNames = var->blockNames; 992 const MatrixData *stateNames = var->stateNames; 993 const MatrixData *crossMdlRef = var->crossMdlRef; 994 const boolean_T logValueDimensions = var->logValueDimensions; 995 int_T i; 996 997 for (i = 0; i < var->numSignals; i++) { 998 /* values */ 999 item.type = matMATRIX; 1000 item.data = &(values->data); 1001 if (cmd) { 1002 if (rt_WriteItemToMatFile(fp, &item,MATRIX_ITEM)) { 1003 retStat = 1; 1004 goto EXIT_POINT; 1005 } 1006 } else { 1007 if (rt_ProcessMatItem(fp, &item, MATRIX_ITEM, 0)) { 1008 retStat = 1; 1009 goto EXIT_POINT; 1010 } 1011 nBytesInItem += item.nbytes + matTAG_SIZE; 1012 } 1013 1014 if(logValueDimensions) 1015 { 1016 /* valueDimensions */ 1017 /* Since the functions rt_WriteItemToMatFile and 1018 rt_ProcessMatItem deal with MatrixData, 1019 convert valDims to tempData, and fill up the 1020 necessary fields. 1021 */ 1022 MatrixData tempData; 1023 (void)memcpy(tempData.name, &VALUEDIMENSIONS_FIELD_NAME, mxMAXNAM); 1024 tempData.nRows = values->valDims->nRows; 1025 tempData.nCols = values->valDims->nCols; 1026 tempData.nDims = 1; 1027 tempData._dims[0] = values->valDims->nCols; 1028 tempData.re = values->valDims->dimsData; 1029 tempData.im = NULL; 1030 tempData.dTypeID = SS_DOUBLE; 1031 tempData.elSize = sizeof(real_T); 1032 tempData.mxID = mxDOUBLE_CLASS; 1033 tempData.logical = 0; 1034 tempData.complex = 0; 1035 tempData.frameData = 0; 1036 tempData.frameSize = 1; 1037 1038 item.type = matMATRIX; 1039 item.data = &tempData; /*values->valDims;*/ 1040 1041 if (cmd) { 1042 if (rt_WriteItemToMatFile(fp, &item,MATRIX_ITEM)) { 1043 retStat = 1; 1044 goto EXIT_POINT; 1045 } 1046 } else { 1047 if (rt_ProcessMatItem(fp, &item, MATRIX_ITEM, 0)) { 1048 retStat = 1; 1049 goto EXIT_POINT; 1050 } 1051 nBytesInItem += item.nbytes + matTAG_SIZE; 1052 } 1053 } 1054 values = values->next; 1055 1056 /* dimensions */ 1057 if (dimensions != NULL) { 1058 item.type = matMATRIX; 1059 item.data = &(dimensions[i]); 1060 if (cmd) { 1061 if (rt_WriteItemToMatFile(fp,&item, MATRIX_ITEM)) { 1062 retStat = 1; 1063 goto EXIT_POINT; 1064 } 1065 } else { 1066 if (rt_ProcessMatItem(fp, &item, MATRIX_ITEM, 0)) { 1067 retStat = 1; 1068 goto EXIT_POINT; 1069 } 1070 nBytesInItem += item.nbytes + matTAG_SIZE; 1071 } 1072 } 1073 1074 /* label */ 1075 item.type = matMATRIX; 1076 item.data = &(labels[i]); 1077 if (cmd) { 1078 if (rt_WriteItemToMatFile(fp, &item,MATRIX_ITEM)) { 1079 retStat = 1; 1080 goto EXIT_POINT; 1081 } 1082 } else { 1083 if (rt_ProcessMatItem(fp, &item, MATRIX_ITEM, 0)) { 1084 retStat = 1; 1085 goto EXIT_POINT; 1086 } 1087 nBytesInItem += item.nbytes + matTAG_SIZE; 1088 } 1089 /* title */ 1090 if (titles != NULL) { 1091 item.type = matMATRIX; 1092 item.data = &(titles[i]); 1093 if (cmd) { 1094 if (rt_WriteItemToMatFile(fp, &item, MATRIX_ITEM)) { 1095 retStat = 1; 1096 goto EXIT_POINT; 1097 } 1098 } else { 1099 if (rt_ProcessMatItem(fp, &item, MATRIX_ITEM, 0)) { 1100 retStat = 1; 1101 goto EXIT_POINT; 1102 } 1103 nBytesInItem += item.nbytes + matTAG_SIZE; 1104 } 1105 } 1106 /* plot style */ 1107 if (plotStyles != NULL) { 1108 item.type = matMATRIX; 1109 item.data = &(plotStyles[i]); 1110 if (cmd) { 1111 if (rt_WriteItemToMatFile(fp,&item, MATRIX_ITEM)) { 1112 retStat = 1; 1113 goto EXIT_POINT; 1114 } 1115 } else { 1116 if (rt_ProcessMatItem(fp, &item, MATRIX_ITEM, 0)) { 1117 retStat = 1; 1118 goto EXIT_POINT; 1119 } 1120 nBytesInItem += item.nbytes + matTAG_SIZE; 1121 } 1122 } 1123 /* block name */ 1124 if (blockNames != NULL) { 1125 item.type = matMATRIX; 1126 item.data = &(blockNames[i]); 1127 if (cmd) { 1128 if (rt_WriteItemToMatFile(fp, &item, MATRIX_ITEM)) { 1129 retStat = 1; 1130 goto EXIT_POINT; 1131 } 1132 } else { 1133 if (rt_ProcessMatItem(fp, &item, MATRIX_ITEM, 0)) { 1134 retStat = 1; 1135 goto EXIT_POINT; 1136 } 1137 nBytesInItem += item.nbytes + matTAG_SIZE; 1138 } 1139 } 1140 /* state name */ 1141 if (stateNames != NULL) { 1142 item.type = matMATRIX; 1143 item.data = &(stateNames[i]); 1144 if (cmd) { 1145 if (rt_WriteItemToMatFile(fp, &item, MATRIX_ITEM)) { 1146 retStat = 1; 1147 goto EXIT_POINT; 1148 } 1149 } else { 1150 if (rt_ProcessMatItem(fp, &item, MATRIX_ITEM, 0)) { 1151 retStat = 1; 1152 goto EXIT_POINT; 1153 } 1154 nBytesInItem += item.nbytes + matTAG_SIZE; 1155 } 1156 } 1157 /* crossMdlRef */ 1158 if (crossMdlRef != NULL) { 1159 item.type = matMATRIX; 1160 item.data = &(crossMdlRef[i]); 1161 if (cmd) { 1162 if (rt_WriteItemToMatFile(fp, &item, MATRIX_ITEM)) { 1163 retStat = 1; 1164 goto EXIT_POINT; 1165 } 1166 } else { 1167 if (rt_ProcessMatItem(fp, &item, MATRIX_ITEM, 0)) { 1168 retStat = 1; 1169 goto EXIT_POINT; 1170 } 1171 nBytesInItem += item.nbytes + matTAG_SIZE; 1172 } 1173 } 1174 } /* for i=1:numSignals */ 1175 break; 1176 } 1177 default: 1178 (void)fprintf(stderr, "Unexpected itemKind=%d in " 1179 "rt_ProcessMatItem @D\n", itemKind); 1180 retStat = -1; 1181 goto EXIT_POINT; 1182 } 1183 } /* end struct item */ 1184 1185 if (!cmd) { 1186 pItem->nbytes = nBytesInItem; 1187 } 1188 1189 EXIT_POINT: 1190 if (dims != _dims) { 1191 FREE(dims); 1192 } 1193 return(retStat); 1194 1195 } /* end rt_ProcessMatItem */ 1196 1197 1198 /* Function: rt_WriteItemToMatFile ============================================= 1199 * Abstract: 1200 * Entry function for writing out a mat item to the mat file. 1201 * 1202 * Return values is 1203 * == 0 : upon success 1204 * <> 0 : upon failure 1205 */ 1206 static int_T rt_WriteItemToMatFile(FILE *fp, 1207 MatItem *pItem, 1208 ItemDataKind itemKind) 1209 { 1210 /* Determine the item size */ 1211 if (pItem->type == matMATRIX) { 1212 if (rt_ProcessMatItem(fp, pItem, itemKind, 0)) return(1); 1213 } 1214 1215 /* Write the item tag and data */ 1216 if (pItem->nbytes > 4) { 1217 int32_T nAlignBytes; 1218 1219 if (fwrite(pItem, 1, matTAG_SIZE, fp) != matTAG_SIZE) return(1); 1220 1221 if (pItem->type == matMATRIX) { 1222 if (rt_ProcessMatItem(fp, pItem, itemKind, 1)) return(1); 1223 } else { 1224 if ( fwrite(pItem->data, 1, pItem->nbytes, fp) != 1225 ((size_t) pItem->nbytes) ) { 1226 return(1); 1227 } 1228 } 1229 1230 /* Add offset for 8-byte alignment */ 1231 nAlignBytes = matINT64_ALIGN(pItem->nbytes) - pItem->nbytes; 1232 if (nAlignBytes > 0) { 1233 int pad[2] = {0, 0}; 1234 if ( fwrite(pad,1,nAlignBytes,fp) != ((size_t) nAlignBytes) ) { 1235 return(1); 1236 } 1237 } 1238 } else { 1239 MatItem item = {0, 0, NULL}; 1240 item.type = ((uint32_T)(pItem->type))|(((uint32_T)(pItem->nbytes))<<16); 1241 (void)memcpy(&item.nbytes, pItem->data, pItem->nbytes); 1242 if (fwrite(&item, 1, matTAG_SIZE, fp) != matTAG_SIZE) return(1); 1243 } 1244 1245 return(0); 1246 1247 } /* end rt_WriteItemToMatFile */ 1248 1249 1250 /* Function: rt_WriteMat5FileHeader ============================================ 1251 * Abstract: 1252 * Function to write the mat file header. 1253 * Return values is 1254 * == 0 : upon success 1255 * <> 0 : upon failure 1256 */ 1257 static int_T rt_WriteMat5FileHeader(FILE *fp) 1258 { 1259 int_T nbytes; 1260 int_T nspaces; 1261 int_T i, n; 1262 unsigned short ver[2]; 1263 char_T spaces[16]; 1264 const char_T *matversion = "MATLAB 5.0 MAT-file"; 1265 1266 (void)memset(spaces, ' ', sizeof(spaces)); 1267 1268 n = (int_T)strlen(matversion); 1269 nbytes = (int_T)fwrite(matversion, 1, n, fp); 1270 /*LINTED E_ASSIGN_INT_TO_SMALL_INT*/ 1271 nspaces = matVERSION_INFO_OFFSET - nbytes; 1272 /*LINTED E_ASSIGN_INT_TO_SMALL_INT*/ 1273 n = nspaces % sizeof(spaces); 1274 nbytes += (int_T)fwrite(spaces, 1, n, fp); 1275 /*LINTED E_ASSIGN_INT_TO_SMALL_INT*/ 1276 n = nspaces / sizeof(spaces); 1277 for (i = 0; i < n; ++i) { 1278 nbytes += (int_T)fwrite(spaces, 1, sizeof(spaces), fp); 1279 } 1280 if (nbytes == matVERSION_INFO_OFFSET) { 1281 ver[0] = matVERSION; 1282 ver[1] = matKEY; 1283 nbytes += (int_T)fwrite(ver, 1, sizeof(ver), fp); 1284 } 1285 return(nbytes != matVERSION_INFO_OFFSET + sizeof(ver)); 1286 1287 } /* end rt_WriteMat5FileHeader */ 1288 1289 1290 /* Function: rt_FixupLogVar ==================================================== 1291 * Abstract: 1292 * Make the logged variable suitable for MATLAB. 1293 */ 1294 static const char_T *rt_FixupLogVar(LogVar *var,int verbose) 1295 { 1296 int_T nCols = var->data.nCols; 1297 int_T maxRows = var->data.nRows; 1298 int_T nDims = var->data.nDims; 1299 size_t elSize = var->data.elSize; 1300 int_T nRows = (var->wrapped ? maxRows : var->rowIdx); 1301 1302 var->nDataPoints = var->rowIdx + var->wrapped * maxRows; 1303 1304 if (var->wrapped > 1 || (var->wrapped == 1 && var->rowIdx != 0)) { 1305 /* 1306 * Warn the user the circular buffer has wrapped, implying that 1307 * some data has been lost. 1308 */ 1309 if( verbose) { 1310 (void)fprintf(stdout, 1311 "*** Log variable %s has wrapped %d times\n" 1312 " using a circular buffer of size %d\n", 1313 var->data.name, var->wrapped, var->data.nRows); 1314 } 1315 if (var->usingDefaultBufSize) { 1316 /* 1317 * If wrapping occurred using the default buffer size, 1318 * let the user know what size buffer to use in the 1319 * future to avoid wrapping. If the default buffer 1320 * size was not used, the user has no control to specify 1321 * the correct value. Wrapping may occur when not using 1322 * the default buffer if we allocated too small a buffer 1323 * size for this logvar. One common case is a toWorkspace 1324 * block inside of an iterative subsystem - we can not take 1325 * the number of iterations into account (they may be 1326 * variable) when allocating the buffer. In this case, 1327 * just warn the buffer wrapped and don't tell user they 1328 * can override the buffer size. 1329 */ 1330 if( verbose ) { 1331 (void)fprintf(stdout, 1332 "*** To avoid wrapping, explicitly specify a\n" 1333 " buffer size of %d in your Simulink model\n" 1334 " by adding OPTS=\"-DDEFAULT_BUFFER_SIZE=%d\"\n" 1335 " as an argument to the ConfigSet MakeCommand\n" 1336 " parameter\n", 1337 var->nDataPoints, var->nDataPoints); 1338 } 1339 } 1340 } 1341 1342 if (nDims < 2 && nCols > 1) { /* Transpose? */ 1343 /* Don't need to transpose valueDimensions */ 1344 int_T nEl = nRows*nCols; 1345 char *src = var->data.re; 1346 char *pmT; 1347 int_T k; 1348 1349 /********************************** 1350 * If memory cannot be allocated, * 1351 * write to a temporary buffer * 1352 **********************************/ 1353 if ((pmT = malloc(nEl*elSize)) == NULL) { 1354 FILE *fptr; 1355 char fName[mxMAXNAM]; 1356 1357 (void)sprintf(fName, "%s%s", var->data.name, "_rtw_tmw.tmw"); 1358 if ((fptr=fopen(fName,"w+b")) == NULL) { 1359 (void)fprintf(stderr,"*** Error opening %s",fName); 1360 return("unable to open data file\n"); 1361 } 1362 1363 /**************************** 1364 * Write the data to a file * 1365 ****************************/ 1366 for (k=0; k<nEl; k++) { 1367 int_T kT = nCols*(k%nRows) + (k/nRows); 1368 char *dst = src + kT*elSize; 1369 (void)fwrite(dst, elSize, 1, fptr); 1370 } 1371 if (var->data.complex) { 1372 char *pmiT = var->data.re; 1373 src = var->data.im; 1374 for (k=0; k<nEl; k++) { 1375 int_T kT = nRows*(k%nCols) + (k/nCols); 1376 char *dst = pmiT + kT*elSize; 1377 (void)memcpy(dst, src, elSize); 1378 src += elSize; 1379 } 1380 var->data.re = var->data.im; 1381 var->data.im = pmiT; 1382 } 1383 1384 /******************************* 1385 * Read the data from the file * 1386 *******************************/ 1387 (void)rewind(fptr); 1388 (void)fread(var->data.re, elSize, nEl, fptr); 1389 (void)fclose(fptr); 1390 (void)remove(fName); 1391 } else { 1392 for (k=0; k<nEl; k++) { 1393 int_T kT = nRows*(k%nCols) + (k/nCols); 1394 char *dst = pmT + kT*elSize; 1395 (void)memcpy(dst, src, elSize); 1396 src += elSize; 1397 } 1398 if (var->data.complex) { 1399 char *pmiT = var->data.re; 1400 src = var->data.im; 1401 for (k=0; k<nEl; k++) { 1402 int_T kT = nRows*(k%nCols) + (k/nCols); 1403 char *dst = pmiT + kT*elSize; 1404 (void)memcpy(dst, src, elSize); 1405 src += elSize; 1406 } 1407 var->data.re = var->data.im; 1408 var->data.im = pmiT; 1409 } 1410 FREE(var->data.re); 1411 var->data.re = pmT; 1412 } 1413 } /* Transpose? */ 1414 1415 if (var->wrapped > 0 && var->rowIdx != 0 ) { /* Rotate? */ 1416 char_T *buffer = var->data.re; 1417 int_T done = 0; /* done: 0 (1) rotate real (imag) part. */ 1418 1419 do { 1420 char_T *col = buffer; 1421 int_T rowOffset = (int_T)((nDims == 1) ? (elSize) : (elSize * nCols)); 1422 int_T colOffset = (int_T)((nDims == 1)? (nRows*elSize) : elSize); 1423 int_T zeroIdx = var->rowIdx; 1424 int_T j; 1425 1426 for (j = 0 ; j < nCols; ++j, col += colOffset) { 1427 int_T swapCount; 1428 int_T srcIdx; 1429 int_T dstIdx; 1430 int_T tmpIdx; 1431 MatReal tmp; 1432 1433 for (tmpIdx=0, swapCount=0; swapCount < nRows; tmpIdx++) { 1434 (void)memcpy(&tmp, col + tmpIdx*rowOffset, elSize); 1435 1436 dstIdx=tmpIdx; 1437 srcIdx = ((dstIdx + zeroIdx) % nRows); 1438 while (srcIdx != tmpIdx) { 1439 (void)memcpy(col + dstIdx*rowOffset, 1440 col + srcIdx*rowOffset, 1441 elSize); 1442 ++swapCount; 1443 dstIdx = srcIdx; 1444 srcIdx = ((dstIdx + zeroIdx) % nRows); 1445 1446 } 1447 (void)memcpy(col + dstIdx*rowOffset, &tmp, elSize); 1448 ++swapCount; 1449 } 1450 } 1451 done ++; 1452 /* need to rotate the imaginary part */ 1453 } while ((done == 1) && ((buffer = var->data.im) != NULL)); 1454 1455 var->rowIdx = 0; 1456 } /* Rotate? */ 1457 1458 /* 1459 * We might have allocated more number of rows than the number of data 1460 * points that have been logged, in which case set nRows to nDataPoints 1461 * so that only these values get saved. 1462 */ 1463 if (var->nDataPoints < var->data.nRows) { 1464 var->data.nRows = var->nDataPoints; 1465 if(var->valDims != NULL){ 1466 size_t elSizeValDims = sizeof(real_T); 1467 int_T k; 1468 real_T *dimsData = var->valDims->dimsData + nRows; 1469 /* 1470 Keep nRows of values and that of valueDimensions consistent 1471 for variable-size signals. 1472 */ 1473 var->valDims->nRows = var->data.nRows; 1474 /* 1475 Also need to move data when shrinking the array size, 1476 because valueDimensions data is stored in array format. 1477 e.g. maxRows = 4; nRows = 2; nDims = 3; 1478 Before fixing up the logVar, the locations of data are as below: 1479 (x, y, z -- useful data / o -- junk) 1480 a[0] = x a[4] = y a[8] = z 1481 a[1] = x a[5] = y a[9] = z 1482 a[2] = o a[6] = o a[10]= o 1483 a[3] = o a[7] = o a[11]= o 1484 After fixing up the logVar, we want the data to be stored as: 1485 a[0] = x a[4] = z a[8] = o 1486 a[1] = x a[5] = z a[9] = o 1487 a[2] = y a[6] = o a[10]= o 1488 a[3] = y a[7] = o a[11]= o 1489 */ 1490 for(k = 1; k < nDims; k++){ 1491 (void) memcpy(dimsData, 1492 var->valDims->dimsData + k*maxRows, 1493 elSizeValDims * nRows); 1494 dimsData += nRows; 1495 } 1496 } 1497 } 1498 return(NULL); 1499 1500 } /* end rt_FixupLogVar */ 1501 1502 1503 /* Function: rt_LoadModifiedLogVarName ========================================= 1504 * Abstract: 1505 * The name of the logged variable is obtained from the input argument 1506 * varName and the nameModifier which is obtained from the simstruct. If 1507 * the nameModifier begins with an '_', then nameModifier is post-pended to 1508 * varName to obtain the name of the logged variable. If the first 1509 * character does not begin with an '_', then the nameModifier is 1510 * pre-pended to varName. 1511 * 1512 * Examples: 1513 * a) varName = "tout" & nameModifier = "_rt" => logVarName = "tout_rt" 1514 * b) varName = "tout" & nameModifier = "rt_" => logVarName = "rt_tout" 1515 * c) varName = "tout" & nameModifier = "none" => logVarName = "tout" 1516 */ 1517 static void rt_LoadModifiedLogVarName(const RTWLogInfo *li, /* in */ 1518 const char *varName, /* in */ 1519 char *logVarName) /* out */ 1520 { 1521 int_T nameLen; 1522 const char_T *nameModifier = rtliGetLogVarNameModifier(li); 1523 1524 if (nameModifier != NULL && strcmp(nameModifier,"none")==0) { 1525 nameModifier = NULL; 1526 } 1527 1528 logVarName[mxMAXNAM-1] = '\0'; 1529 if (nameModifier == NULL) { 1530 (void)strncpy(logVarName, varName, mxMAXNAM-1); 1531 } else if (nameModifier[0] == '_') { 1532 (void)strncpy(logVarName, varName, mxMAXNAM-1); 1533 nameLen = (int_T)strlen(logVarName); 1534 (void)strncat(logVarName, nameModifier, mxMAXNAM-1-nameLen); 1535 } else { 1536 (void)strncpy(logVarName, nameModifier, mxMAXNAM-1); 1537 nameLen = (int_T)strlen(logVarName); 1538 (void)strncat(logVarName, varName, mxMAXNAM-1-nameLen); 1539 } 1540 1541 } /* end rt_LoadModifiedLogVarName */ 1542 1543 1544 /* Function: rt_GetActualDTypeID =============================================== 1545 * Abstract: 1546 * Given a built-in data type id, return the actual data type id. 1547 * The only time these are different is when real_T has been mapped 1548 * to a single. 1549 */ 1550 static BuiltInDTypeId rt_GetActualDTypeID(BuiltInDTypeId dTypeID) 1551 { 1552 /*LINTED E_FALSE_LOGICAL_EXPR*/ 1553 if (dTypeID == SS_DOUBLE && sizeof(real_T) != 8) { 1554 return(SS_SINGLE); 1555 } else { 1556 return(dTypeID); 1557 } 1558 1559 } /* end rt_GetActualDTypeID */ 1560 1561 1562 /* Function: rt_DestroyLogVar ================================================== 1563 * Abstract: 1564 * Destroy the log var linked list. 1565 */ 1566 static void rt_DestroyLogVar(LogVar *head) 1567 { 1568 while(head) { 1569 LogVar *var = head; 1570 head = var->next; 1571 FREE(var->data.re); 1572 FREE(var->data.im); 1573 if (var->data.dims != var->data._dims) { 1574 FREE(var->data.dims); 1575 } 1576 /* free valDims if necessary */ 1577 if(var->valDims != NULL) { 1578 FREE(var->valDims->dimsData); 1579 FREE(var->valDims); 1580 } 1581 /* free coords, strides and currStrides if necessary */ 1582 FREE(var->coords); 1583 FREE(var->strides); 1584 FREE(var->currStrides); 1585 1586 FREE(var); 1587 } 1588 1589 } /* end rt_DestroyLogVar */ 1590 1591 1592 /* Function: rt_DestroyStructLogVar ============================================ 1593 * Abstract: 1594 * Destroy the struct log var linked list. 1595 */ 1596 static void rt_DestroyStructLogVar(StructLogVar *head) 1597 { 1598 while(head) { 1599 StructLogVar *var = head; 1600 1601 head = var->next; 1602 1603 if (var->logTime) { /* time is LogVar */ 1604 rt_DestroyLogVar(var->time); 1605 } else { /* time is MatrixData */ 1606 FREE(var->time); 1607 } 1608 rt_DestroyLogVar(var->signals.values); 1609 FREE(var->signals.labels); 1610 FREE(var->signals.plotStyles); 1611 FREE(var->signals.dimensions); 1612 FREE(var->signals.titles); 1613 FREE(var->signals.blockNames); 1614 FREE(var->signals.stateNames); 1615 FREE(var->signals.crossMdlRef); 1616 FREE(var->blockName); 1617 FREE(var); 1618 } 1619 1620 } /* end rt_DestroyStructLogVar */ 1621 1622 1623 /* Function: rt_InitSignalsStruct ============================================== 1624 * Abstract: 1625 * Initialize the signals structure in the struct log variable. 1626 * 1627 * Returns: 1628 * == NULL => success. 1629 * ~= NULL => failure, the return value is a pointer to the error 1630 * message, which is also set in the simstruct. 1631 */ 1632 static const char_T *rt_InitSignalsStruct(RTWLogInfo *li, 1633 const real_T startTime, 1634 const real_T finalTime, 1635 const real_T inStepSize, 1636 const char_T **errStatus, 1637 StructLogVar *var, 1638 int_T maxRows, 1639 int_T decimation, 1640 real_T sampleTime, 1641 const RTWLogSignalInfo *sigInfo) 1642 { 1643 int_T i, sigIdx; 1644 SignalsStruct *sig = &(var->signals); 1645 int_T nSignals = sigInfo->numSignals; 1646 const int_T *numCols = sigInfo->numCols; 1647 const int_T *numDims = sigInfo->numDims; 1648 const int_T *dims = sigInfo->dims; 1649 const BuiltInDTypeId *dTypes = sigInfo->dataTypes; 1650 const int_T *cSgnls = sigInfo->complexSignals; 1651 const int_T *fData = sigInfo->frameData; 1652 const char_T **labels = sigInfo->labels.cptr; 1653 const int_T *plotStyles = sigInfo->plotStyles; 1654 const char_T *titles = sigInfo->titles; 1655 const int_T *titleLen = sigInfo->titleLengths; 1656 const char_T **blockNames = sigInfo->blockNames.cptr; 1657 const char_T **stateNames = sigInfo->stateNames.cptr; 1658 const boolean_T *crossMdlRef = sigInfo->crossMdlRef; 1659 1660 void **currSigDims = sigInfo->currSigDims; 1661 int_T *currSigDimsSize = sigInfo->currSigDimsSize; 1662 LogVar *prevValues = NULL; 1663 int_T dimsOffset = 0; 1664 boolean_T *isVarDims = sigInfo->isVarDims; 1665 /* if any signal is variable-size, the field 'valueDimensions' is needed */ 1666 boolean_T logValueDimensions = false; 1667 const RTWLogDataTypeConvert *pDTConvInfo = sigInfo->dataTypeConvert; 1668 1669 /* reset error status */ 1670 *errStatus = NULL; 1671 1672 sig->numActiveFields = 1; 1673 sig->numSignals = nSignals; 1674 1675 sig->isVarDims = isVarDims; 1676 /* check whether we need valueDimensions field*/ 1677 for (i=0; i<nSignals; i++){ 1678 if(isVarDims[i]){ 1679 logValueDimensions = true; 1680 break; 1681 } 1682 } 1683 1684 /* values */ 1685 dimsOffset = 0; 1686 for (i = 0; i < nSignals; i++) { 1687 BuiltInDTypeId dt = (dTypes) ? dTypes[i] : SS_DOUBLE; 1688 int_T cs = (cSgnls) ? cSgnls[i] : 0; 1689 int_T fd = (fData) ? fData[i] : 0; 1690 int_T nd = (numDims) ? numDims[i] : 1; 1691 1692 const RTWLogDataTypeConvert *pDTConvInfoCur = 1693 (pDTConvInfo) ? (pDTConvInfo+i) : 0; 1694 1695 LogVar *values = NULL; 1696 LogValDimsStat logValDimsStat; 1697 1698 if(!logValueDimensions){ 1699 logValDimsStat = NO_LOGVALDIMS; 1700 } 1701 else{ 1702 logValDimsStat = isVarDims[i] ? LOGVALDIMS_VARDIMS : 1703 LOGVALDIMS_EMPTYMX; 1704 } 1705 1706 values = rt_CreateLogVarWithConvert(li, startTime, finalTime, 1707 inStepSize, errStatus, 1708 &VALUES_FIELD_NAME, 1709 dt, 1710 pDTConvInfoCur, 1711 0, cs, fd, 1712 numCols[i],nd, 1713 dims + dimsOffset, 1714 logValDimsStat, 1715 currSigDims + dimsOffset, 1716 currSigDimsSize + dimsOffset, 1717 maxRows,decimation,sampleTime, 0); 1718 1719 if (values == NULL) goto ERROR_EXIT; 1720 1721 if (sig->values == NULL) { 1722 sig->values = values; 1723 } else { 1724 prevValues->next = values; 1725 } 1726 prevValues = values; 1727 dimsOffset += nd; 1728 } 1729 1730 if(logValueDimensions){ 1731 ++sig->numActiveFields; 1732 sig->logValueDimensions = true; 1733 } 1734 else{ 1735 sig->logValueDimensions = false; 1736 } 1737 1738 /* Dimensions */ 1739 { 1740 real_T *data; 1741 size_t nbytes; 1742 int_T dataLen = 0; 1743 BuiltInDTypeId dTypeId = rt_GetActualDTypeID(SS_DOUBLE); 1744 size_t dataOffset = nSignals*sizeof(MatrixData); 1745 uint_T overhang = (uint_T)(dataOffset % sizeof(real_T)); 1746 1747 if (overhang) { 1748 dataOffset += (sizeof(real_T) - overhang); 1749 } 1750 for (i=0; i< nSignals; i++) { 1751 int_T nd = (numDims) ? numDims[i] : 1; 1752 dataLen += nd; 1753 } 1754 nbytes = dataOffset + dataLen*sizeof(real_T); 1755 1756 if ( (sig->dimensions = calloc(nbytes, 1)) == NULL ) goto ERROR_EXIT; 1757 1758 data = (real_T*) (((char_T*) (sig->dimensions)) + dataOffset); 1759 1760 for (i = 0; i < dataLen; i++) { 1761 data[i] = dims[i]; /* cannot memcpy double <- int */ 1762 } 1763 1764 for (i = 0; i < nSignals; i++) { 1765 MatrixData *mtxData = &(sig->dimensions[i]); 1766 int_T nd = (numDims) ? numDims[i] : 1; 1767 1768 (void)memcpy(mtxData->name, &DIMENSION_FIELD_NAME, mxMAXNAM); 1769 1770 mtxData->nRows = 1; 1771 mtxData->nCols = nd; 1772 1773 mtxData->nDims = 1; /* assume */ 1774 mtxData->dims = mtxData->_dims; 1775 mtxData->dims[0] = mtxData->nCols; 1776 1777 mtxData->re = data; 1778 mtxData->im = NULL; 1779 mtxData->dTypeID = dTypeId; 1780 mtxData->mxID = rt_GetMxIdFromDTypeId(dTypeId); 1781 mtxData->elSize = rt_GetSizeofDataType(dTypeId); 1782 mtxData->logical = 0U; 1783 mtxData->complex = 0U; 1784 1785 data += nd; 1786 } 1787 ++sig->numActiveFields; 1788 } 1789 1790 /* labels */ 1791 if (labels != NULL) { 1792 short *data; 1793 size_t nbytes; 1794 int_T dataLen = 0; 1795 size_t dataOffset = nSignals * sizeof(MatrixData); 1796 uint_T overhang = (uint_T)(dataOffset % sizeof(short)); 1797 int_T dataIdx = 0; 1798 1799 for (i=0;i<nSignals;i++) { 1800 if (labels[i] != NULL){ 1801 dataLen = dataLen + (int_T)strlen(labels[i]); 1802 } 1803 } 1804 1805 if (overhang) { 1806 dataOffset += (sizeof(short) - overhang); 1807 } 1808 nbytes = dataOffset + dataLen*sizeof(short); 1809 1810 if ( (sig->labels = calloc(nbytes, 1)) == NULL ) goto ERROR_EXIT; 1811 1812 data = (short*) (((char_T*) (sig->labels)) + dataOffset); 1813 for(sigIdx=0;sigIdx<nSignals;sigIdx++) { 1814 int_T labelLen = (labels[sigIdx]==NULL) ? 0 : (int_T)strlen(labels[sigIdx]); 1815 for (i = 0; i < labelLen; i++) { 1816 data[dataIdx++] = labels[sigIdx][i]; 1817 } 1818 } 1819 1820 for (i = 0; i < nSignals; i++) { 1821 MatrixData *mtxData = &(sig->labels[i]); 1822 int_T labelLen = (int_T)strlen(labels[i]); 1823 1824 (void)memcpy(mtxData->name, &LABEL_FIELD_NAME, mxMAXNAM); 1825 mtxData->nRows = (labelLen) ? 1 : 0; 1826 mtxData->nCols = labelLen; 1827 1828 mtxData->re = data; 1829 mtxData->im = NULL; 1830 1831 mtxData->nDims = 1; /* assume */ 1832 mtxData->dims = mtxData->_dims; 1833 mtxData->dims[0] = mtxData->nCols; 1834 1835 mtxData->dTypeID = SS_INT16; 1836 mtxData->mxID = mxCHAR_CLASS; 1837 mtxData->elSize = sizeof(short); 1838 mtxData->logical = 0U; 1839 mtxData->complex = 0U; 1840 1841 data += labelLen; 1842 } 1843 ++sig->numActiveFields; 1844 } 1845 1846 /* plot styles */ 1847 if (plotStyles != NULL) { 1848 real_T *data; 1849 size_t nbytes; 1850 int_T dataLen = 0; 1851 BuiltInDTypeId dTypeId = rt_GetActualDTypeID(SS_DOUBLE); 1852 /*LINTED E_ASSIGN_INT_TO_SMALL_INT*/ 1853 size_t dataOffset = nSignals*sizeof(MatrixData); 1854 /*LINTED E_ASSIGN_INT_TO_SMALL_INT*/ 1855 uint_T overhang = (uint_T)(dataOffset % sizeof(real_T)); 1856 1857 if (overhang) { 1858 dataOffset += (sizeof(real_T) - overhang); 1859 } 1860 for (i=0; i< nSignals; i++) { 1861 dataLen += numCols[i]; 1862 } 1863 /*LINTED E_ASSIGN_INT_TO_SMALL_INT*/ 1864 nbytes = dataOffset + dataLen*sizeof(real_T); 1865 1866 if ( (sig->plotStyles = calloc(nbytes, 1)) == NULL ) goto ERROR_EXIT; 1867 1868 /*LINTED E_BAD_PTR_CAST_ALIGN*/ 1869 data = (real_T*) (((char_T*) (sig->plotStyles)) + dataOffset); 1870 1871 for (i = 0; i < dataLen; i++) { 1872 data[i] = plotStyles[i]; 1873 } 1874 1875 dimsOffset = 0; 1876 for (i = 0; i < nSignals; i++) { 1877 MatrixData *mtxData = &(sig->plotStyles[i]); 1878 1879 (void)memcpy(mtxData->name, &PLOTSTYLE_FIELD_NAME, mxMAXNAM); 1880 1881 mtxData->nRows = (numCols[i]) ? 1 : 0; 1882 mtxData->nCols = numCols[i]; 1883 1884 mtxData->nDims = numDims[i]; 1885 1886 if(mtxData->nDims > 2) { 1887 if ((mtxData->dims = calloc(mtxData->nDims, sizeof(int_T))) == NULL) goto ERROR_EXIT; 1888 } else { 1889 mtxData->dims = mtxData->_dims; 1890 } 1891 1892 mtxData->dims[0] = *(dims + dimsOffset); 1893 if(mtxData->nDims >= 2) { 1894 int32_T j; 1895 for (j=1; j<mtxData->nDims; j++) { 1896 mtxData->dims[j] = *(dims + dimsOffset + j); 1897 } 1898 } 1899 1900 mtxData->re = data; 1901 mtxData->im = NULL; 1902 mtxData->dTypeID = dTypeId; 1903 mtxData->mxID = rt_GetMxIdFromDTypeId(dTypeId); 1904 mtxData->elSize = rt_GetSizeofDataType(dTypeId); 1905 mtxData->logical = 0U; 1906 mtxData->complex = 0U; 1907 1908 data += numCols[i]; 1909 dimsOffset += numDims[i]; 1910 } 1911 ++sig->numActiveFields; 1912 } 1913 1914 /* titles */ 1915 if (titles != NULL) { 1916 short *data; 1917 size_t nbytes; 1918 int_T dataLen = (int_T)strlen(titles); 1919 /*LINTED E_ASSIGN_INT_TO_SMALL_INT*/ 1920 size_t dataOffset = nSignals * sizeof(MatrixData); 1921 /*LINTED E_ASSIGN_INT_TO_SMALL_INT*/ 1922 uint_T overhang = (uint_T)(dataOffset % sizeof(short)); 1923 1924 if (overhang) { 1925 dataOffset += (sizeof(short) - overhang); 1926 } 1927 /*LINTED E_ASSIGN_INT_TO_SMALL_INT*/ 1928 nbytes = dataOffset + dataLen*sizeof(short); 1929 1930 if ( (sig->titles = calloc(nbytes, 1)) == NULL ) goto ERROR_EXIT; 1931 1932 /*LINTED E_BAD_PTR_CAST_ALIGN*/ 1933 data = (short*) (((char_T*) (sig->titles)) + dataOffset); 1934 for (i = 0; i < dataLen; i++) { 1935 data[i] = titles[i]; 1936 } 1937 1938 for (i = 0; i < nSignals; i++) { 1939 MatrixData *mtxData = &(sig->titles[i]); 1940 1941 (void)memcpy(mtxData->name, &TITLE_FIELD_NAME, mxMAXNAM); 1942 if (titleLen) { 1943 mtxData->nRows = (titleLen[i]) ? 1 : 0; 1944 mtxData->nCols = titleLen[i]; 1945 } else { 1946 mtxData->nRows = (dataLen) ? 1 : 0; 1947 mtxData->nCols = dataLen; 1948 } 1949 1950 mtxData->nDims = 1; /* assume */ 1951 mtxData->dims = mtxData->_dims; 1952 mtxData->dims[0] = mtxData->nCols; 1953 1954 mtxData->re = data; 1955 mtxData->im = NULL; 1956 mtxData->dTypeID = SS_INT16; 1957 mtxData->mxID = mxCHAR_CLASS; 1958 mtxData->elSize = sizeof(short); 1959 mtxData->logical = 0U; 1960 mtxData->complex = 0U; 1961 1962 data += ((titleLen) ? titleLen[i] : dataLen); 1963 } 1964 ++sig->numActiveFields; 1965 } 1966 1967 /* block names */ 1968 if (blockNames != NULL) { 1969 short *data; 1970 size_t nbytes; 1971 int_T dataLen = 0; 1972 size_t dataOffset = nSignals * sizeof(MatrixData); 1973 uint_T overhang = (uint_T)(dataOffset % sizeof(short)); 1974 int_T dataIdx = 0; 1975 1976 for (i=0;i<nSignals;i++) { 1977 if (blockNames[i] != NULL) { 1978 dataLen = dataLen + (int_T)strlen(blockNames[i]); 1979 } 1980 } 1981 1982 if (overhang) { 1983 dataOffset += (sizeof(short) - overhang); 1984 } 1985 1986 nbytes = dataOffset + dataLen*sizeof(short); 1987 1988 if ( (sig->blockNames = calloc(nbytes, 1)) == NULL ) goto ERROR_EXIT; 1989 1990 data = (short*) (((char_T*) (sig->blockNames)) + dataOffset); 1991 1992 for(sigIdx=0;sigIdx<nSignals;sigIdx++) { 1993 int_T nameLen = (blockNames[sigIdx]==NULL) ? 0 : 1994 (int_T)strlen(blockNames[sigIdx]); 1995 for (i = 0; i < nameLen; i++) { 1996 data[dataIdx++] = blockNames[sigIdx][i]; 1997 } 1998 } 1999 2000 for (i = 0; i < nSignals; i++) { 2001 MatrixData *mtxData = &(sig->blockNames[i]); 2002 int_T blockNameLen = (int_T)strlen(blockNames[i]); 2003 2004 (void)memcpy(mtxData->name, &BLOCKNAME_FIELD_NAME, mxMAXNAM); 2005 mtxData->nRows = (blockNameLen) ? 1 : 0; 2006 mtxData->nCols = blockNameLen; 2007 2008 mtxData->nDims = 1; /* assume */ 2009 mtxData->dims = mtxData->_dims; 2010 mtxData->dims[0] = mtxData->nCols; 2011 2012 mtxData->re = data; 2013 mtxData->im = NULL; 2014 mtxData->dTypeID = SS_INT16; 2015 mtxData->mxID = mxCHAR_CLASS; 2016 mtxData->elSize = sizeof(short); 2017 mtxData->logical = 0U; 2018 mtxData->complex = 0U; 2019 2020 data += blockNameLen; 2021 } 2022 ++sig->numActiveFields; 2023 if(logValueDimensions){ 2024 sig->fieldNames = rtGlobalLoggingSignalsStructFieldNames; 2025 } 2026 else{ 2027 sig->fieldNames = rtGlobalLoggingSignalsStructFieldNames_noValDims; 2028 } 2029 2030 } else { 2031 if(logValueDimensions){ 2032 sig->fieldNames = rtLocalLoggingSignalsStructFieldNames; 2033 } 2034 else{ 2035 sig->fieldNames = rtLocalLoggingSignalsStructFieldNames_noValDims; 2036 } 2037 2038 } 2039 2040 /* state names */ 2041 if (stateNames != NULL) { 2042 short *data; 2043 size_t nbytes; 2044 int_T dataLen = 0; 2045 size_t dataOffset = nSignals * sizeof(MatrixData); 2046 uint_T overhang = (uint_T)(dataOffset % sizeof(short)); 2047 int_T dataIdx = 0; 2048 2049 for (i=0;i<nSignals;i++) { 2050 if (stateNames[i] != NULL) { 2051 dataLen = dataLen + (int_T)strlen(stateNames[i]); 2052 } 2053 } 2054 2055 if (overhang) { 2056 dataOffset += (sizeof(short) - overhang); 2057 } 2058 2059 nbytes = dataOffset + dataLen*sizeof(short); 2060 2061 if ( (sig->stateNames = calloc(nbytes, 1)) == NULL ) goto ERROR_EXIT; 2062 2063 data = (short*) (((char_T*) (sig->stateNames)) + dataOffset); 2064 2065 for(sigIdx=0;sigIdx<nSignals;sigIdx++) { 2066 int_T nameLen = (stateNames[sigIdx]==NULL) ? 0 : 2067 (int_T)strlen(stateNames[sigIdx]); 2068 for (i = 0; i < nameLen; i++) { 2069 data[dataIdx++] = stateNames[sigIdx][i]; 2070 } 2071 } 2072 2073 for (i = 0; i < nSignals; i++) { 2074 MatrixData *mtxData = &(sig->stateNames[i]); 2075 int_T stateNameLen = (int_T)strlen(stateNames[i]); 2076 2077 (void)memcpy(mtxData->name, &STATENAME_FIELD_NAME, mxMAXNAM); 2078 mtxData->nRows = (stateNameLen) ? 1 : 0; 2079 mtxData->nCols = stateNameLen; 2080 2081 mtxData->nDims = 1; /* assume */ 2082 mtxData->dims = mtxData->_dims; 2083 mtxData->dims[0] = mtxData->nCols; 2084 2085 mtxData->re = data; 2086 mtxData->im = NULL; 2087 mtxData->dTypeID = SS_INT16; 2088 mtxData->mxID = mxCHAR_CLASS; 2089 mtxData->elSize = sizeof(short); 2090 mtxData->logical = 0U; 2091 mtxData->complex = 0U; 2092 2093 data += stateNameLen; 2094 } 2095 ++sig->numActiveFields; 2096 2097 if(logValueDimensions){ 2098 sig->fieldNames = rtGlobalLoggingSignalsStructFieldNames; 2099 } 2100 else{ 2101 sig->fieldNames = rtGlobalLoggingSignalsStructFieldNames_noValDims; 2102 } 2103 2104 } 2105 2106 /* CrossMdlRef */ 2107 if (crossMdlRef != NULL) { 2108 real_T *data; 2109 size_t nbytes; 2110 size_t dataOffset = nSignals * sizeof(MatrixData); 2111 uint_T overhang = (uint_T)(dataOffset % sizeof(real_T)); 2112 2113 if (overhang) { 2114 dataOffset += (sizeof(real_T) - overhang); 2115 } 2116 2117 nbytes = dataOffset + nSignals*sizeof(real_T); 2118 2119 if ( (sig->crossMdlRef = calloc(nbytes, 1)) == NULL ) goto ERROR_EXIT; 2120 2121 data = (real_T*) (((char_T*) (sig->crossMdlRef)) + dataOffset); 2122 2123 for(sigIdx=0;sigIdx<nSignals;sigIdx++) { 2124 data[sigIdx] = crossMdlRef[sigIdx]; 2125 } 2126 2127 for (i = 0; i < nSignals; i++) { 2128 MatrixData *mtxData = &(sig->crossMdlRef[i]); 2129 2130 (void)memcpy(mtxData->name, &CROSS_MDL_REF_FIELD_NAME, mxMAXNAM); 2131 mtxData->nRows = 1; 2132 mtxData->nCols = 1; 2133 mtxData->nDims = 1; /* => matlab scalar */ 2134 2135 mtxData->re = &data[i]; 2136 mtxData->im = NULL; 2137 mtxData->dTypeID = SS_DOUBLE; 2138 mtxData->mxID = rt_GetMxIdFromDTypeId(SS_DOUBLE); 2139 mtxData->elSize = sizeof(real_T); 2140 mtxData->logical = matLOGICAL_BIT; 2141 mtxData->complex = 0U; 2142 mtxData->frameData = 0; 2143 mtxData->frameSize = 1; 2144 } 2145 ++sig->numActiveFields; 2146 } 2147 2148 return(NULL); /* NORMAL_EXIT */ 2149 2150 ERROR_EXIT: 2151 2152 (void)fprintf(stderr, "*** Error creating signals structure " 2153 "in the struct log variable %s\n", var->name); 2154 if (*errStatus == NULL) { 2155 *errStatus = rtMemAllocError; 2156 } 2157 rt_DestroyLogVar(sig->values); 2158 FREE(sig->labels); 2159 FREE(sig->plotStyles); 2160 FREE(sig->dimensions); 2161 FREE(sig->titles); 2162 FREE(sig->blockNames); 2163 FREE(sig->stateNames); 2164 FREE(sig->crossMdlRef); 2165 2166 return(*errStatus); 2167 2168 } /* end rt_InitSignalsStruct */ 2169 2170 2171 /* Function: local_CreateStructLogVar ========================================== 2172 * Abstract: 2173 * Create a logging variable in the structure format. 2174 * 2175 * Returns: 2176 * ~= NULL => success, returns the log variable created. 2177 * == NULL => failure, error message set in the simstruct. 2178 */ 2179 static StructLogVar *local_CreateStructLogVar( 2180 RTWLogInfo *li, 2181 const real_T startTime, 2182 const real_T finalTime, 2183 const real_T inStepSize, 2184 const char_T **errStatus, 2185 const char_T *varName, 2186 boolean_T logTime, 2187 int_T maxRows, 2188 int_T decimation, 2189 real_T sampleTime, 2190 const RTWLogSignalInfo *sigInfo, 2191 const char_T *blockName) 2192 { 2193 StructLogVar *var; 2194 LogInfo *logInfo = rtliGetLogInfo(li); 2195 2196 /* reset error status */ 2197 *errStatus = NULL; 2198 2199 if ( (var = calloc(1, sizeof(StructLogVar))) == NULL ) goto ERROR_EXIT; 2200 2201 var->numActiveFields = 2; 2202 2203 /* Setup the structure name using varName and nameModifier */ 2204 rt_LoadModifiedLogVarName(li,varName,var->name); 2205 2206 /* time field */ 2207 if (logTime) { 2208 /* need to create a LogVar to log time */ 2209 int_T dims = 1; 2210 var->time = rt_CreateLogVarWithConvert(li, startTime, finalTime, 2211 inStepSize, errStatus, 2212 &TIME_FIELD_NAME, SS_DOUBLE, 2213 NULL, 2214 0, 0, 0, 1, 2215 1, &dims, NO_LOGVALDIMS, 2216 NULL, NULL, maxRows, 2217 decimation, sampleTime, 0); 2218 if (var->time == NULL) goto ERROR_EXIT; 2219 } else { 2220 /* create a dummy MatrixData to write out time as an empty matrix */ 2221 BuiltInDTypeId dt = rt_GetActualDTypeID(SS_DOUBLE); 2222 size_t nbytes = sizeof(MatrixData); 2223 MatrixData *time; 2224 2225 if ( (var->time = calloc(nbytes, 1)) == NULL ) goto ERROR_EXIT; 2226 time = var->time; 2227 2228 (void)memcpy(time->name, &TIME_FIELD_NAME, mxMAXNAM); 2229 time->nRows = 0; 2230 time->nCols = 0; 2231 time->nDims = 0; 2232 time->re = NULL; 2233 time->im = NULL; 2234 time->dTypeID = dt; 2235 time->mxID = rt_GetMxIdFromDTypeId(dt); 2236 time->elSize = rt_GetSizeofDataType(dt); 2237 time->logical = 0U; 2238 time->complex = 0U; 2239 } 2240 var->logTime = logTime; 2241 2242 /* signals field */ 2243 if (sigInfo) { 2244 if (rt_InitSignalsStruct(li,startTime,finalTime,inStepSize,errStatus, 2245 var,maxRows,decimation,sampleTime,sigInfo)) { 2246 goto ERROR_EXIT; 2247 } 2248 } 2249 2250 /* blockName Field */ 2251 if (blockName != NULL) { 2252 int_T dataLen = (int_T)strlen(blockName); 2253 size_t nbytes; 2254 size_t dataOffset = sizeof(MatrixData); 2255 /*LINTED E_ASSIGN_INT_TO_SMALL_INT*/ 2256 uint_T overhang = (uint_T)(dataOffset % sizeof(short)); 2257 2258 if (overhang) { 2259 dataOffset += (sizeof(short) - overhang); 2260 } 2261 /*LINTED E_ASSIGN_INT_TO_SMALL_INT*/ 2262 nbytes = dataOffset + dataLen*sizeof(short); 2263 2264 if ( (var->blockName = calloc(nbytes, 1)) == NULL ) goto ERROR_EXIT; 2265 2266 (void)memcpy(var->blockName->name, &BLOCKNAME_FIELD_NAME, mxMAXNAM); 2267 var->blockName->nRows = (dataLen) ? 1 : 0; 2268 var->blockName->nCols = dataLen; 2269 2270 var->blockName->nDims = 1; 2271 var->blockName->dims = var->blockName->_dims; 2272 var->blockName->dims[0] = dataLen; 2273 { 2274 /*LINTED E_BAD_PTR_CAST_ALIGN*/ 2275 short *data = (short*)(((char_T*) (var->blockName))+dataOffset); 2276 int_T i; 2277 2278 for (i=0; i<dataLen; i++) { 2279 data[i] = blockName[i]; 2280 } 2281 var->blockName->re = data; 2282 } 2283 var->blockName->im = NULL; 2284 var->blockName->dTypeID = SS_INT16; 2285 var->blockName->mxID = mxCHAR_CLASS; 2286 var->blockName->elSize = sizeof(short); 2287 var->blockName->logical = 0U; 2288 var->blockName->complex = 0U; 2289 2290 ++var->numActiveFields; 2291 } 2292 2293 /* Add this struct log var to the linked list in log info */ 2294 { 2295 StructLogVar *list = logInfo->structLogVarsList; 2296 2297 if (list != NULL) { 2298 while (list->next != NULL) { 2299 list = list->next; 2300 } 2301 list->next = var; 2302 } else { 2303 logInfo->structLogVarsList = var; 2304 } 2305 } 2306 2307 return(var); /* NORMAL_EXIT */ 2308 2309 ERROR_EXIT: 2310 (void)fprintf(stderr, "*** Error creating log variable %s\n", varName); 2311 if (*errStatus == NULL) { 2312 *errStatus = rtMemAllocError; 2313 } 2314 rt_DestroyStructLogVar(var); 2315 return(NULL); 2316 2317 } /* end local_CreateStructLogVar */ 2318 2319 2320 /* Function: rt_StartDataLoggingForOutput ====================================== 2321 * Abstract: 2322 */ 2323 const char_T *rt_StartDataLoggingForOutput(RTWLogInfo *li, 2324 const real_T startTime, 2325 const real_T finalTime, 2326 const real_T stepSize, 2327 const char_T **errStatus) 2328 { 2329 const char_T *varName; 2330 real_T sampleTime = stepSize; 2331 int_T maxRows = rtliGetLogMaxRows(li); 2332 int_T decimation = rtliGetLogDecimation(li); 2333 int_T logFormat = rtliGetLogFormat(li); 2334 boolean_T logTime = (logFormat==2) ? 1 : 0; 2335 2336 LogInfo * logInfo; 2337 logInfo = rtliGetLogInfo(li); 2338 2339 /* reset error status */ 2340 *errStatus = NULL; 2341 2342 /* outputs */ 2343 varName = rtliGetLogY(li); 2344 if (varName[0] != '\0') { 2345 int_T i; 2346 int_T ny; 2347 int_T yIdx; 2348 char_T name[mxMAXNAM]; 2349 const char_T *cp = strchr(varName,','); 2350 LogSignalPtrsType ySigPtrs = rtliGetLogYSignalPtrs(li); 2351 const RTWLogSignalInfo *yInfo = rtliGetLogYSignalInfo(li); 2352 2353 /* count the number of variables (matrices or structures) to create */ 2354 for (ny=1; cp != NULL; ny++) { 2355 cp = strchr(cp+1,','); 2356 } 2357 logInfo->ny = ny; 2358 2359 if (logFormat==0) { 2360 if ( (logInfo->y = calloc(ny,sizeof(LogVar*))) == NULL ) { 2361 *errStatus = rtMemAllocError; 2362 goto ERROR_EXIT; 2363 } 2364 } else { 2365 if ( (logInfo->y = calloc(ny,sizeof(StructLogVar*))) == NULL ) { 2366 *errStatus = rtMemAllocError; 2367 goto ERROR_EXIT; 2368 } 2369 } 2370 2371 for (i = yIdx = 0, cp = varName; i < ny; i++) { 2372 int_T len; 2373 const char_T *cp1 = strchr(cp+1,','); 2374 2375 if (cp1 != NULL) { 2376 /*LINTED E_ASSIGN_INT_TO_SMALL_INT*/ 2377 len = (int_T)(cp1 - cp); 2378 if (len >= mxMAXNAM) len = mxMAXNAM - 1; 2379 } else { 2380 len = mxMAXNAM - 1; 2381 } 2382 (void)strncpy(name, cp, len); 2383 name[len] = '\0'; 2384 2385 if (ny > 1 && ySigPtrs[i] == NULL) { 2386 goto NEXT_NAME; 2387 } 2388 2389 if (logFormat == 0) { 2390 int numCols; 2391 int nDims; 2392 const int *dims; 2393 BuiltInDTypeId dataType; 2394 int isComplex; 2395 2396 if (ny == 1) { 2397 int_T op; 2398 2399 numCols = yInfo[0].numCols[0]; 2400 for (op = 1; op < yInfo[0].numSignals; op++) { 2401 numCols += yInfo[0].numCols[op]; 2402 } 2403 /* 2404 * If we have only one "matrix" outport, 2405 * we can still log it as a matrix 2406 */ 2407 if (yInfo[0].numSignals == 1) { 2408 nDims = yInfo[0].numDims[0]; 2409 dims = yInfo[0].dims; 2410 } else { 2411 nDims = 1; 2412 dims = &numCols; 2413 } 2414 2415 dataType = yInfo[0].dataTypes[0]; 2416 isComplex = yInfo[0].complexSignals[0]; 2417 } else { 2418 numCols = yInfo[yIdx].numCols[0]; 2419 nDims = yInfo[yIdx].numDims[0]; 2420 dims = yInfo[yIdx].dims; 2421 dataType = yInfo[yIdx].dataTypes[0]; 2422 isComplex = yInfo[yIdx].complexSignals[0]; 2423 } 2424 2425 logInfo->y[yIdx] = rt_CreateLogVarWithConvert( 2426 li, startTime, finalTime, 2427 stepSize, errStatus, 2428 name, 2429 dataType, 2430 yInfo[yIdx].dataTypeConvert, 2431 0,isComplex, 2432 0,numCols,nDims,dims, 2433 NO_LOGVALDIMS, NULL, NULL, 2434 maxRows,decimation, 2435 sampleTime,1); 2436 if (logInfo->y[yIdx] == NULL) goto ERROR_EXIT; 2437 } else { 2438 logInfo->y[yIdx] = local_CreateStructLogVar(li, startTime, 2439 finalTime, stepSize, 2440 errStatus, name, 2441 logTime, maxRows, 2442 decimation, sampleTime, 2443 &yInfo[yIdx], NULL); 2444 if (logInfo->y[yIdx] == NULL) goto ERROR_EXIT; 2445 } 2446 ++yIdx; 2447 NEXT_NAME: 2448 cp = cp1; 2449 if (cp != NULL && *cp == ',') cp++; 2450 } 2451 } 2452 2453 return(NULL); /* NORMAL_EXIT */ 2454 2455 ERROR_EXIT: 2456 (void)fprintf(stderr, "*** Errors occurred when starting data logging.\n"); 2457 if (*errStatus == NULL) { 2458 *errStatus = rtMemAllocError; 2459 } 2460 if (logInfo) { 2461 rt_DestroyLogVar(logInfo->logVarsList); 2462 logInfo->logVarsList = NULL; 2463 rt_DestroyStructLogVar(logInfo->structLogVarsList); 2464 logInfo->structLogVarsList = NULL; 2465 FREE(logInfo->y); 2466 logInfo->y = NULL; 2467 } 2468 return(*errStatus); 2469 2470 } /* end rt_StartDataLoggingForOutput */ 2471 2472 2473 /* Function: rt_ReallocLogVar ================================================== 2474 * Abstract: 2475 * Allocate more memory for the data buffers in the log variable. 2476 * Exit if unable to allocate more memory. 2477 */ 2478 void rt_ReallocLogVar(LogVar *var, boolean_T isVarDims) 2479 { 2480 void *tmp; 2481 int_T nCols = var->data.nCols; 2482 int_T nRows = var->data.nRows + DEFAULT_BUFFER_SIZE; 2483 size_t elSize = var->data.elSize; 2484 2485 tmp = realloc(var->data.re, nRows*nCols*elSize); 2486 if (tmp == NULL) { 2487 (void)fprintf(stderr, 2488 "*** Memory allocation error.\n"); 2489 (void)fprintf(stderr, "" 2490 " varName = %s%s\n" 2491 " nRows = %d\n" 2492 " nCols = %d\n" 2493 " elementSize = %lu\n" 2494 " Current Size = %.16g\n" 2495 " Failed resize = %.16g\n\n", 2496 var->data.name, 2497 var->data.complex ? " (real part)" : "", 2498 var->data.nRows, 2499 var->data.nCols, 2500 (long) var->data.elSize, 2501 (double)nRows*nCols*elSize, 2502 (double)(nRows+DEFAULT_BUFFER_SIZE)*nCols*elSize); 2503 exit(1); 2504 } 2505 var->data.re = tmp; 2506 2507 if (var->data.complex) { 2508 tmp = realloc(var->data.im, nRows*nCols*elSize); 2509 if (tmp == NULL) { 2510 (void)fprintf(stderr, 2511 "*** Memory allocation error.\n"); 2512 (void)fprintf(stderr, "" 2513 " varName = %s (complex part)\n" 2514 " nRows = %d\n" 2515 " nCols = %d\n" 2516 " elementSize = %lu\n" 2517 " Current Size = %.16g\n" 2518 " Failed resize = %.16g\n\n", 2519 var->data.name, 2520 var->data.nRows, 2521 var->data.nCols, 2522 (long) var->data.elSize, 2523 (double)nRows*nCols*elSize, 2524 (double)(nRows+DEFAULT_BUFFER_SIZE)*nCols*elSize); 2525 exit(1); 2526 } 2527 var->data.im = tmp; 2528 } 2529 var->data.nRows = nRows; 2530 2531 /* Also reallocate memory for "valueDimensions" 2532 when logging the variable-size signal 2533 */ 2534 if(isVarDims){ 2535 int_T k; 2536 2537 nCols = var->valDims->nCols; 2538 nRows = var->valDims->nRows + DEFAULT_BUFFER_SIZE; 2539 elSize = sizeof(real_T); 2540 tmp = realloc(var->valDims->dimsData, nRows*nCols*elSize); 2541 if (tmp == NULL) { 2542 (void)fprintf(stderr, 2543 "*** Memory allocation error.\n"); 2544 (void)fprintf(stderr, "" 2545 " varName = %s\n" 2546 " nRows = %d\n" 2547 " nCols = %d\n" 2548 " elementSize = %lu\n" 2549 " Current Size = %.16g\n" 2550 " Failed resize = %.16g\n\n", 2551 var->valDims->name, 2552 var->valDims->nRows, 2553 var->valDims->nCols, 2554 (long) elSize, 2555 (double)nRows*nCols*elSize, 2556 (double)(nRows+DEFAULT_BUFFER_SIZE)*nCols*elSize); 2557 exit(1); 2558 } 2559 2560 /* 2561 * valueDimensions data is stored in array format and must be 2562 * adjusted after reallocation (see also rt_FixupLogVar()) 2563 * 2564 * Example: maxRows = 4; nRows = 4; nDims = 3; 2565 * Before realloc of the logVar, the locations of data are as below: 2566 * (x, y, z -- useful data / o -- junk, don't care) 2567 * a[0] = x a[4] = y a[8] = z 2568 * a[1] = x a[5] = y a[9] = z 2569 * a[2] = x a[6] = y a[10]= z 2570 * a[3] = x a[7] = y a[11]= z 2571 * 2572 * After realloc of the logVar (suppose 2 extra rows are added), 2573 * the locations of data are as below: 2574 * a[0] = x a[6] = y a[12]= o 2575 * a[1] = x a[7] = y a[13]= o 2576 * a[2] = x a[8] = z a[14]= o 2577 * a[3] = x a[9] = z a[15]= o 2578 * a[4] = y a[10]= z a[16]= o 2579 * a[5] = y a[11]= z a[17]= o 2580 * 2581 * The data must be adjusted as below: 2582 * a[0] = x a[6] = y a[12]= z 2583 * a[1] = x a[7] = y a[13]= z 2584 * a[2] = x a[8] = y a[14]= z 2585 * a[3] = x a[9] = y a[15]= z 2586 * a[4] = o a[10]= o a[16]= o 2587 * a[5] = o a[11]= o a[17]= o 2588 */ 2589 for(k = var->data.nDims-1; k > 0; k--){ 2590 (void) memcpy((real_T*)tmp + k*nRows, 2591 (real_T*)tmp + k*var->valDims->nRows, 2592 elSize * var->valDims->nRows); 2593 } 2594 2595 var->valDims->dimsData = tmp; 2596 var->valDims->nRows = nRows; 2597 } 2598 2599 } /* end rt_ReallocLogVar */ 2600 2601 2602 /* Function: rt_UpdateLogVarWithDiscontiguousData ============================== 2603 * Abstract: 2604 * Log one row of the LogVar with data that is not contiguous. 2605 */ 2606 void rt_UpdateLogVarWithDiscontiguousData(LogVar *var, 2607 LogSignalPtrsType data, 2608 const int_T *segmentLengths, 2609 int_T nSegments) 2610 { 2611 size_t elSize = 0; 2612 int_T offset = 0; 2613 int segIdx = 0; 2614 2615 if (++var->numHits % var->decimation) return; 2616 var->numHits = 0; 2617 2618 /* 2619 * Reallocate or wrap the LogVar 2620 */ 2621 if (var->rowIdx == var->data.nRows) { 2622 if (var->okayToRealloc == 1) { 2623 rt_ReallocLogVar(var, false); 2624 } else { 2625 /* Circular buffer */ 2626 var->rowIdx = 0; 2627 ++(var->wrapped); /* increment the wrap around counter */ 2628 } 2629 } 2630 2631 /* This function is only used to log states, there's no var-dims issue. */ 2632 elSize = var->data.elSize; 2633 offset = (int_T)(elSize * var->rowIdx * var->data.nCols); 2634 2635 if (var->data.complex) { 2636 char_T *dstRe = (char_T*)(var->data.re) + offset; 2637 char_T *dstIm = (char_T*)(var->data.im) + offset; 2638 2639 for (segIdx = 0; segIdx < nSegments; segIdx++) { 2640 int_T nEl = segmentLengths[segIdx]; 2641 const char_T *src = (void *)data[segIdx]; 2642 int_T el; 2643 2644 for (el = 0; el < nEl; el++) { 2645 (void)memcpy(dstRe, src, elSize); 2646 dstRe += elSize; src += elSize; 2647 (void)memcpy(dstIm, src, elSize); 2648 dstIm += elSize; src += elSize; 2649 } 2650 } 2651 } else { 2652 char_T *dst = (char_T*)(var->data.re) + offset; 2653 2654 for (segIdx = 0; segIdx < nSegments; segIdx++) { 2655 size_t segSize = elSize*segmentLengths[segIdx]; 2656 const void *src = data[segIdx]; 2657 2658 (void)memcpy(dst, src, segSize); 2659 dst += segSize; 2660 } 2661 } 2662 2663 ++var->rowIdx; 2664 return; 2665 2666 } /* end rt_UpdateLogVarWithDiscontiguousData */ 2667 2668 2669 /*==================* 2670 * Visible routines * 2671 *==================*/ 2672 2673 2674 BEGIN_PUBLIC 2675 #ifdef __cplusplus 2676 extern "C" { 2677 #endif 2678 END_PUBLIC 2679 2680 /* Function: rt_CreateLogVarWithConvert ======================================== 2681 * Abstract: 2682 * Create a logging variable. 2683 * 2684 * Returns: 2685 * ~= NULL => success, returns the log variable created. 2686 * == NULL => failure, error message set in the simstruct. 2687 */ 2688 PUBLIC LogVar *rt_CreateLogVarWithConvert( 2689 RTWLogInfo *li, 2690 const real_T startTime, 2691 const real_T finalTime, 2692 const real_T inStepSize, 2693 const char_T **errStatus, 2694 const char_T *varName, 2695 BuiltInDTypeId inpDataTypeID, 2696 const RTWLogDataTypeConvert *pDataTypeConvertInfo, 2697 int_T logical, 2698 int_T complex, 2699 int_T frameData, 2700 int_T nCols, 2701 int_T nDims, 2702 const int_T *dims, 2703 LogValDimsStat logValDimsStat, 2704 void **currSigDims, 2705 int_T *currSigDimsSize, 2706 int_T maxRows, 2707 int_T decimation, 2708 real_T sampleTime, 2709 int_T appendToLogVarsList) 2710 { 2711 int_T usingDefaultBufSize = 0; 2712 #ifdef NO_LOGGING_REALLOC 2713 int_T okayToRealloc = 0; 2714 #else 2715 int_T okayToRealloc = 1; 2716 #endif 2717 LogVar *var = NULL; 2718 /*inpDataTypeID is the rt_LoggedOutputDataTypeId*/ 2719 BuiltInDTypeId dTypeID = (BuiltInDTypeId)inpDataTypeID; 2720 size_t elementSize = rt_GetSizeofDataType(dTypeID); 2721 int_T frameSize; 2722 int_T nRows; 2723 int_T nColumns; 2724 2725 /*===================================================================* 2726 * Determine the frame size if the data is frame based * 2727 *===================================================================*/ 2728 frameSize = frameData ? dims[0] : 1; 2729 2730 /*===================================================================* 2731 * Calculate maximum number of rows needed in the buffer * 2732 *===================================================================*/ 2733 2734 if (finalTime > startTime && finalTime != rtInf) { 2735 real_T nPoints; /* Tfinal is finite ===> nRows can be */ 2736 real_T stepSize; /* computed since the StepSize is fixed */ 2737 2738 if (sampleTime == -2.0) { /* The signal being logged is constant, * 2739 * Hence, only one data point is logged. */ 2740 stepSize = finalTime; 2741 } else if (sampleTime == -1.0 || sampleTime == 0.0) { 2742 /* Signal being logged is either inside a * 2743 * triggered sub-system or it is continuous. */ 2744 stepSize = inStepSize; 2745 } else { /* Discrete signal */ 2746 stepSize = sampleTime; 2747 } 2748 2749 if (stepSize == 0.0) { 2750 /* small initial value, so as to exercise the realloc code */ 2751 nRows = maxRows+1; 2752 okayToRealloc = 1; 2753 } else { 2754 nPoints = 1.0 + floor((finalTime-startTime)/stepSize); 2755 2756 /* 2757 * Add one more data point if needed. 2758 */ 2759 if ( stepSize*(nPoints-1.0) < (finalTime-startTime) ) { 2760 nPoints += 1.0; 2761 } 2762 2763 /* 2764 * Actual number of points to log = nPoints * size of 2765 * each frame if data is frame-based 2766 */ 2767 nPoints = frameData ? (nPoints * frameSize) : nPoints; 2768 2769 nPoints /= decimation; 2770 if (nPoints != floor(nPoints)) { 2771 nPoints += 1.0; 2772 } 2773 nRows = (nPoints <= INT_MAX) ? ((int_T) nPoints) : INT_MAX; 2774 } 2775 /* 2776 * If maxRows is specified, and if this number is less 2777 * than the number we computed (nRows) then use maxRows. 2778 */ 2779 if ((maxRows > 0) && (maxRows < nRows)) { 2780 nRows = maxRows; 2781 okayToRealloc = 0; 2782 } 2783 } else if (finalTime == startTime) { 2784 /* 2785 * Number of rows to log is equal to 1 if not frame-based and 2786 * equal to frame size if frame-based 2787 */ 2788 nRows = frameData ? frameSize : 1; 2789 2790 /* 2791 * If maxRows is specified, and if this number is less 2792 * than the number we computed (nRows) then use maxRows. 2793 */ 2794 if ((maxRows > 0) && (maxRows < nRows)) { 2795 nRows = maxRows; 2796 okayToRealloc = 0; 2797 } 2798 } else if (maxRows > 0) { /* maxRows is specified => nRows=maxRows */ 2799 nRows = maxRows; 2800 okayToRealloc = 0; 2801 } else { 2802 2803 if (inStepSize == 0) { 2804 /* small initial value, so as to exercise the realloc code */ 2805 nRows = maxRows+1; 2806 okayToRealloc = 1; 2807 } else { /* Use a default value for nRows */ 2808 usingDefaultBufSize = 1; 2809 nRows = DEFAULT_BUFFER_SIZE; 2810 okayToRealloc = 0; /* No realloc with infinite stop time */ 2811 (void)fprintf(stdout, "*** Using a default buffer of size %d for " 2812 "logging variable %s\n", nRows, varName); 2813 } 2814 } 2815 2816 /* 2817 * Figure out the number of columns that the log variable should have. 2818 * If the data is not frame based, then number of columns should equal 2819 * nCols that is provided as input to the function. If the data is 2820 * frame-based, then the number of columns should be equal to the 2821 * number of channels = nCols/frameSize = dims[1]; 2822 */ 2823 nColumns = frameData ? dims[1] : nCols; 2824 2825 /* 2826 * Error out if the size of the circular buffer is absurdly large, this 2827 * error message is more informative than the one we get when we try to 2828 * malloc this many number of bytes in one fell swoop. 2829 */ 2830 { 2831 double tmpDbl = ((double)elementSize)*((double)nRows)* 2832 ((double)nColumns); 2833 2834 if (tmpDbl >= UINT_MAX) { 2835 (void)fprintf(stderr, 2836 "\n*** Memory required to log variable '%s' is too" 2837 "\n big. Use the 'Limit rows to last:' and (or)" 2838 "\n 'Decimation:' options to reduce the required" 2839 "\n memory size.\n", varName); 2840 (void)fprintf(stderr, "*** Details:\n" 2841 " varName = %s\n" 2842 " nRows = %d\n" 2843 " nCols = %d\n" 2844 " elementSize = %lu\n" 2845 " Bytes Required = %.16g\n\n", 2846 varName, nRows, nColumns, (unsigned long) 2847 elementSize, tmpDbl); 2848 goto ERROR_EXIT; 2849 } 2850 } 2851 2852 /* Allocate memory for the log variable */ 2853 if ( (var = calloc(1, sizeof(LogVar))) == NULL ) { 2854 (void)fprintf(stderr, "*** Error allocating memory for logging %s\n", 2855 varName); 2856 goto ERROR_EXIT; 2857 } 2858 2859 /* Allocate memory for the circular buffer (real part) */ 2860 if ( (var->data.re = malloc(nRows*nColumns*elementSize)) == NULL ) { 2861 (void)fprintf(stderr, 2862 "*** Error allocating memory for the circular buffer\n"); 2863 (void)fprintf(stderr, "*** Details:\n" 2864 " varName = %s\n" 2865 " nRows = %d\n" 2866 " nCols = %d\n" 2867 " elementSize = %lu\n" 2868 " Bytes Requested = %.16g\n\n", 2869 varName, nRows, nColumns, (unsigned long) elementSize, 2870 ((double)elementSize)*((double)nRows)*((double)nColumns)); 2871 goto ERROR_EXIT; 2872 } 2873 2874 /* Allocate memory for the circular buffer for the imaginary part */ 2875 if (complex) { 2876 if ( (var->data.im = malloc(nRows*nColumns*elementSize)) == NULL ) { 2877 (void)fprintf(stderr, 2878 "*** Error allocating memory for the circular buffer " 2879 "for logging the imaginary part of %s\n", varName); 2880 (void)fprintf(stderr, "*** Details:\n" 2881 " varName = %s\n" 2882 " nRows = %d\n" 2883 " nCols = %d\n" 2884 " elementSize = %lu\n" 2885 " Bytes Requested = %.16g\n\n", 2886 varName, nRows, nColumns, (unsigned long) elementSize, 2887 ((double)elementSize)*((double)nRows)* 2888 ((double)nColumns)); 2889 goto ERROR_EXIT; 2890 } 2891 } 2892 /* 2893 * Initialize the fields in LogVar structure. 2894 */ 2895 if (appendToLogVarsList) { 2896 rt_LoadModifiedLogVarName(li,varName,var->data.name); 2897 } else { 2898 var->data.name[mxMAXNAM-1] = '\0'; 2899 (void)strncpy(var->data.name,varName,mxMAXNAM-1); 2900 } 2901 var->data.nCols = nColumns; 2902 var->data.nRows = nRows; 2903 2904 var->data.nDims = frameData ? 1 : nDims; 2905 if (var->data.nDims > 2) { 2906 var->data.dims = (int_T*)malloc(sizeof(int_T)*var->data.nDims); 2907 } else { 2908 var->data.dims = var->data._dims; 2909 } 2910 if (frameData) { 2911 var->data.dims[0] = nColumns; 2912 } else { 2913 /*LINTED E_CAST_INT_TO_SMALL_INT*/ 2914 (void)memcpy(var->data.dims, dims, (size_t)(nDims*sizeof(int_T))); 2915 } 2916 2917 var->data.dTypeID = dTypeID; 2918 var->data.elSize = elementSize; 2919 2920 var->data.dataTypeConvertInfo = rt_GetDataTypeConvertInfo( 2921 pDataTypeConvertInfo, dTypeID); 2922 2923 var->data.mxID = rt_GetMxIdFromDTypeId(dTypeID); 2924 /* over-ride logical bit if data type is boolean */ 2925 logical = dTypeID == SS_BOOLEAN ? 1 : 0; 2926 var->data.logical = (logical) ? matLOGICAL_BIT : 0x0; 2927 var->data.complex = (complex) ? matCOMPLEX_BIT : 0x0; 2928 var->data.frameData = frameData; 2929 var->data.frameSize = (frameData) ? frameSize : 1; 2930 2931 /* fill up valDims field */ 2932 if(logValDimsStat == NO_LOGVALDIMS){ 2933 /* All signals are fixed-size, no need to log valueDimensions field */ 2934 var->valDims = NULL; 2935 /* Set these pointers to NULLs in this case */ 2936 var->coords = NULL; 2937 var->strides = NULL; 2938 var->currStrides = NULL; 2939 } 2940 else{ 2941 if ( (var->valDims = calloc(1, sizeof(ValDimsData))) == NULL ) { 2942 goto ERROR_EXIT; 2943 } 2944 2945 (void)memcpy(var->valDims->name, &VALUEDIMENSIONS_FIELD_NAME, mxMAXNAM); 2946 2947 if (logValDimsStat == LOGVALDIMS_EMPTYMX) { 2948 /* At least one signal is variable-size, 2949 but the current signal is fixed-size. 2950 Therefore, create a dummy MatrixData to write out valueDimensions 2951 as an empty matrix. 2952 */ 2953 var->valDims->nRows = 0; 2954 var->valDims->nCols = 0; 2955 var->valDims->currSigDims = NULL; 2956 var->valDims->currSigDimsSize = NULL; 2957 var->valDims->dimsData = NULL; 2958 /* Set these pointers to NULLs in this case */ 2959 var->coords = NULL; 2960 var->strides = NULL; 2961 var->currStrides = NULL; 2962 } else { /* The current signal is a variable-size signal. */ 2963 /* The "valueDimensions" must be double, so re-assign element size */ 2964 elementSize = sizeof(real_T); 2965 2966 /* When signals are frame-based, 'valueDimensions' has 1 column */ 2967 if(frameData){ 2968 /* When signal is frame-based, the first dimension is always fixed, 2969 so we only need to record the second dimension. 2970 e.g. Two frame-based signals [10x4] and [10x3], 2971 'valueDimensions' and 'currSigDims' 2972 only record 4 or 3. 2973 */ 2974 nColumns = 1; 2975 var->valDims->currSigDims = (void**) (currSigDims + 1); 2976 var->valDims->currSigDimsSize = (int_T*) (currSigDimsSize + 1); 2977 } else { /* non-frame based */ 2978 nColumns = nDims; 2979 var->valDims->currSigDims = (void**) currSigDims; 2980 var->valDims->currSigDimsSize = (int_T*) currSigDimsSize; 2981 } 2982 2983 /* Allocate memory for the circular buffer */ 2984 if ( (var->valDims->dimsData = malloc(nRows*nColumns*elementSize)) == NULL ) { 2985 (void)fprintf(stderr, 2986 "*** Error allocating memory for the circular buffer\n"); 2987 (void)fprintf(stderr, "*** Details:\n" 2988 " varName = %s\n" 2989 " nRows = %d\n" 2990 " nCols = %d\n" 2991 " elementSize = %lu\n" 2992 " Bytes Requested = %.16g\n\n", 2993 var->valDims->name, nRows, nColumns, (unsigned long) elementSize, 2994 ((double)elementSize)*((double)nRows)*((double)nColumns)); 2995 goto ERROR_EXIT; 2996 } 2997 var->valDims->nRows = nRows; 2998 var->valDims->nCols = nColumns; 2999 3000 /* Allocate memory for these dynamic arrays */ 3001 { 3002 size_t nbytes = var->data.nDims*sizeof(int_T); 3003 if( ((var->coords = calloc(nbytes, 1)) == NULL) 3004 ||((var->strides = calloc(nbytes, 1)) == NULL) 3005 ||((var->currStrides = calloc(nbytes, 1)) == NULL) ) 3006 goto ERROR_EXIT; 3007 } 3008 } 3009 } 3010 3011 var->rowIdx = 0; 3012 var->wrapped = 0; 3013 var->nDataPoints = 0; 3014 var->usingDefaultBufSize = usingDefaultBufSize; 3015 var->okayToRealloc = okayToRealloc; 3016 var->decimation = decimation; 3017 var->numHits = -1; /* so first point gets logged */ 3018 3019 /* Add this log var to list in log info, if necessary */ 3020 if (appendToLogVarsList) { 3021 LogInfo *logInfo = (LogInfo*) rtliGetLogInfo(li); 3022 LogVar *varList = logInfo->logVarsList; 3023 3024 if (varList != NULL) { 3025 while (varList->next != NULL) { 3026 varList = varList->next; 3027 } 3028 varList->next = var; 3029 } else { 3030 logInfo->logVarsList = var; 3031 } 3032 } 3033 3034 return(var); /* NORMAL_EXIT */ 3035 3036 ERROR_EXIT: 3037 3038 *errStatus = rtMemAllocError; 3039 rt_DestroyLogVar(var); 3040 return(NULL); 3041 3042 } /* end rt_CreateLogVarWithConvert */ 3043 3044 BEGIN_PUBLIC 3045 #ifdef __cplusplus 3046 } 3047 #endif 3048 END_PUBLIC 3049 3050 3051 BEGIN_PUBLIC 3052 #ifdef __cplusplus 3053 extern "C" { 3054 #endif 3055 END_PUBLIC 3056 3057 /* Function: rt_CreateLogVar =================================================== 3058 * Abstract: 3059 * Create a logging variable. 3060 * 3061 * Returns: 3062 * ~= NULL => success, returns the log variable created. 3063 * == NULL => failure, error message set in the simstruct. 3064 */ 3065 PUBLIC LogVar *rt_CreateLogVar(RTWLogInfo *li, 3066 const real_T startTime, 3067 const real_T finalTime, 3068 const real_T inStepSize, 3069 const char_T **errStatus, 3070 const char_T *varName, 3071 BuiltInDTypeId inpDataTypeID, 3072 int_T logical, 3073 int_T complex, 3074 int_T frameData, 3075 int_T nCols, 3076 int_T nDims, 3077 const int_T *dims, 3078 LogValDimsStat logValDimsStat, 3079 void **currSigDims, 3080 int_T *currSigDimsSize, 3081 int_T maxRows, 3082 int_T decimation, 3083 real_T sampleTime, 3084 int_T appendToLogVarsList) 3085 { 3086 const RTWLogDataTypeConvert *pDataTypeConvertInfo = NULL; 3087 3088 return rt_CreateLogVarWithConvert(li, 3089 startTime, 3090 finalTime, 3091 inStepSize, 3092 errStatus, 3093 varName, 3094 inpDataTypeID, 3095 pDataTypeConvertInfo, 3096 logical, 3097 complex, 3098 frameData, 3099 nCols, 3100 nDims, 3101 dims, 3102 logValDimsStat, 3103 currSigDims, 3104 currSigDimsSize, 3105 maxRows, 3106 decimation, 3107 sampleTime, 3108 appendToLogVarsList); 3109 3110 } /* end rt_CreateLogVar */ 3111 3112 BEGIN_PUBLIC 3113 #ifdef __cplusplus 3114 } 3115 #endif 3116 END_PUBLIC 3117 3118 3119 BEGIN_PUBLIC 3120 #ifdef __cplusplus 3121 extern "C" { 3122 #endif 3123 END_PUBLIC 3124 3125 /* Function: rt_CreateStructLogVar ============================================= 3126 * Abstract: 3127 * Create a logging variable in the structure format. 3128 * 3129 * Returns: 3130 * ~= NULL => success, returns the log variable created. 3131 * == NULL => failure, error message set in the simstruct. 3132 */ 3133 PUBLIC StructLogVar *rt_CreateStructLogVar(RTWLogInfo *li, 3134 const real_T startTime, 3135 const real_T finalTime, 3136 const real_T inStepSize, 3137 const char_T **errStatus, 3138 const char_T *varName, 3139 boolean_T logTime, 3140 int_T maxRows, 3141 int_T decimation, 3142 real_T sampleTime, 3143 const RTWLogSignalInfo *sigInfo, 3144 const char_T *blockName) 3145 { 3146 3147 return( local_CreateStructLogVar(li, 3148 startTime, 3149 finalTime, 3150 inStepSize, 3151 errStatus, 3152 varName, 3153 logTime, 3154 maxRows, 3155 decimation, 3156 sampleTime, 3157 sigInfo, 3158 blockName)); 3159 3160 } /* end rt_CreateStructLogVar */ 3161 3162 BEGIN_PUBLIC 3163 #ifdef __cplusplus 3164 } 3165 #endif 3166 END_PUBLIC 3167 3168 3169 BEGIN_PUBLIC 3170 #ifdef __cplusplus 3171 extern "C" { 3172 #endif 3173 END_PUBLIC 3174 3175 /* Function: rt_StartDataLoggingWithStartTime ================================== 3176 * Abstract: 3177 * Initialize data logging info based upon the following settings cached 3178 * in the RTWLogging data structure of the SimStruct. 3179 * 3180 * Return value is: 3181 * == NULL => success 3182 * != NULL => failure (the return value is a pointer that points to the 3183 * error message, which is also set in the simstruct) 3184 */ 3185 PUBLIC const char_T *rt_StartDataLoggingWithStartTime(RTWLogInfo *li, 3186 const real_T startTime, 3187 const real_T finalTime, 3188 const real_T stepSize, 3189 const char_T **errStatus) 3190 { 3191 const char_T *varName; 3192 LogInfo *logInfo; 3193 real_T sampleTime = stepSize; 3194 int_T maxRows = rtliGetLogMaxRows(li); 3195 int_T decimation = rtliGetLogDecimation(li); 3196 int_T logFormat = rtliGetLogFormat(li); 3197 boolean_T logTime = (logFormat==2) ? 1 : 0; 3198 3199 /* reset error status */ 3200 *errStatus = NULL; 3201 3202 if ((logInfo=calloc(1,sizeof(LogInfo))) == NULL) { 3203 *errStatus = rtMemAllocError; 3204 goto ERROR_EXIT; 3205 } 3206 rtliSetLogInfo(li, (void*)logInfo); 3207 3208 /* time */ 3209 varName = rtliGetLogT(li); 3210 if (varName[0] != '\0') { 3211 int_T dims = 1; 3212 logInfo->t = rt_CreateLogVarWithConvert(li, startTime, finalTime, 3213 stepSize, errStatus, 3214 varName,SS_DOUBLE, 3215 NULL, 3216 0,0,0,1,1, 3217 &dims, NO_LOGVALDIMS, NULL, NULL, 3218 maxRows,decimation, 3219 sampleTime,1); 3220 if (logInfo->t == NULL) goto ERROR_EXIT; 3221 } 3222 3223 /* states */ 3224 if ( rtliGetLogX(li)[0] != '\0' || rtliGetLogXFinal(li)[0] != '\0' ) { 3225 const RTWLogSignalInfo *xInfo = rtliGetLogXSignalInfo(li); 3226 3227 if (logFormat == 0) { /* Matrix Format */ 3228 int numCols; 3229 int nDims; 3230 const int *dims; 3231 BuiltInDTypeId dataType; 3232 int isComplex; 3233 int_T sIdx; 3234 3235 const RTWLogDataTypeConvert *pDTConvInfo; 3236 3237 numCols = xInfo[0].numCols[0]; 3238 for (sIdx = 1; sIdx < xInfo[0].numSignals; sIdx++) { 3239 numCols += xInfo[0].numCols[sIdx]; 3240 } 3241 /* If we have only one "matrix" state, we can log as a matrix */ 3242 if (xInfo[0].numSignals == 1) { 3243 nDims = xInfo[0].numDims[0]; 3244 dims = xInfo[0].dims; 3245 } else { 3246 nDims = 1; 3247 dims = &numCols; 3248 } 3249 dataType = xInfo[0].dataTypes[0]; 3250 isComplex = xInfo[0].complexSignals[0]; 3251 3252 pDTConvInfo = xInfo[0].dataTypeConvert; 3253 3254 if (rtliGetLogX(li)[0] != '\0') { 3255 logInfo->x = rt_CreateLogVarWithConvert(li, startTime, finalTime, 3256 stepSize, errStatus, 3257 rtliGetLogX(li),dataType, 3258 pDTConvInfo, 3259 0, 3260 isComplex,0,numCols,nDims,dims, 3261 NO_LOGVALDIMS, NULL, NULL, 3262 maxRows,decimation,sampleTime,1); 3263 if (logInfo->x == NULL) goto ERROR_EXIT; 3264 } 3265 if (rtliGetLogXFinal(li)[0] != '\0') { 3266 logInfo->xFinal = rt_CreateLogVarWithConvert(li, startTime, finalTime, 3267 stepSize, errStatus, 3268 rtliGetLogXFinal(li),dataType, 3269 pDTConvInfo, 3270 0,isComplex,0,numCols,nDims, 3271 dims, NO_LOGVALDIMS, NULL, 3272 NULL, 1,decimation, 3273 sampleTime,1); 3274 if (logInfo->xFinal == NULL) goto ERROR_EXIT; 3275 } 3276 } else { /* Structure Format */ 3277 if (rtliGetLogX(li)[0] != '\0') { 3278 logInfo->x = local_CreateStructLogVar(li, startTime, finalTime, 3279 stepSize, errStatus, 3280 rtliGetLogX(li), logTime, 3281 maxRows, decimation, 3282 sampleTime, xInfo, NULL); 3283 if (logInfo->x == NULL) goto ERROR_EXIT; 3284 } 3285 if (rtliGetLogXFinal(li)[0] != '\0') { 3286 logInfo->xFinal = local_CreateStructLogVar(li, startTime, finalTime, 3287 stepSize, errStatus, 3288 rtliGetLogXFinal(li), 3289 logTime,1,decimation, 3290 sampleTime,xInfo,NULL); 3291 if (logInfo->xFinal == NULL) goto ERROR_EXIT; 3292 } 3293 } 3294 } 3295 3296 /* signal logging */ 3297 if ( rtliGetSigLog(li)[0] != '\0' ) { 3298 const RTWLogSignalInfo *slInfo = rtliGetSigLogSignalInfo(li); 3299 3300 /* log using structure format */ 3301 logInfo->sl = local_CreateStructLogVar(li, startTime, finalTime, 3302 stepSize, errStatus, 3303 rtliGetSigLog(li), logTime, 3304 maxRows, decimation, 3305 sampleTime, slInfo, NULL); 3306 if (logInfo->sl == NULL) goto ERROR_EXIT; 3307 } 3308 3309 /* outputs */ 3310 *errStatus = rt_StartDataLoggingForOutput(li,startTime,finalTime, 3311 stepSize,errStatus); 3312 if (*errStatus != NULL) goto ERROR_EXIT; 3313 3314 return(NULL); /* NORMAL_EXIT */ 3315 3316 ERROR_EXIT: 3317 (void)fprintf(stderr, "*** Errors occurred when starting data logging.\n"); 3318 if (*errStatus == NULL) { 3319 *errStatus = rtMemAllocError; 3320 } 3321 if (logInfo) { 3322 rt_DestroyLogVar(logInfo->logVarsList); 3323 logInfo->logVarsList = NULL; 3324 rt_DestroyStructLogVar(logInfo->structLogVarsList); 3325 logInfo->structLogVarsList = NULL; 3326 } 3327 return(*errStatus); 3328 3329 } /* end rt_StartDataLoggingWithStartTime */ 3330 3331 BEGIN_PUBLIC 3332 #ifdef __cplusplus 3333 } 3334 #endif 3335 END_PUBLIC 3336 3337 3338 BEGIN_PUBLIC 3339 #ifdef __cplusplus 3340 extern "C" { 3341 #endif 3342 END_PUBLIC 3343 3344 /* Function: rt_StartDataLogging =============================================== 3345 * Abstract: 3346 */ 3347 PUBLIC const char_T *rt_StartDataLogging(RTWLogInfo *li, 3348 const real_T finalTime, 3349 const real_T stepSize, 3350 const char_T **errStatus) 3351 { 3352 return rt_StartDataLoggingWithStartTime(li, 3353 0.0, 3354 finalTime, 3355 stepSize, 3356 errStatus); 3357 } 3358 3359 BEGIN_PUBLIC 3360 #ifdef __cplusplus 3361 } 3362 #endif 3363 END_PUBLIC 3364 3365 3366 BEGIN_PUBLIC 3367 #ifdef __cplusplus 3368 extern "C" { 3369 #endif 3370 END_PUBLIC 3371 3372 /* Function: rt_UpdateLogVar =================================================== 3373 * Abstract: 3374 * Called to log data for a log variable. 3375 */ 3376 PUBLIC void rt_UpdateLogVar(LogVar *var, const void *data, boolean_T isVarDims) 3377 { 3378 size_t elSize = var->data.elSize; 3379 const char_T *cData = data; 3380 const int_T frameData = var->data.frameData; 3381 const int_T frameSize = frameData ? (var->data.frameSize) : 1; 3382 const int_T logWidth = var->data.nCols; 3383 BuiltInDTypeId dTypeID = var->data.dTypeID; 3384 3385 int_T offset = 0; 3386 char_T *currRealRow = NULL; 3387 char_T *currImagRow = NULL; 3388 int_T pointSize = (int_T)((var->data.complex) ? rt_GetSizeofComplexType(dTypeID) : elSize); 3389 3390 int i, j, k; 3391 3392 /* The following variables will be used for 3393 logging variable-size signals */ 3394 const int_T nDims = var->data.nDims; 3395 const int_T *dims = var->data.dims; 3396 const void **currDimsPtr = NULL; 3397 const int_T *currDimsSizePtr = NULL; 3398 3399 /* The following variables will be used for 3400 logging "valueDimensions" field */ 3401 int_T offset_valDims = 0; 3402 char_T *currValDimsRow = NULL; 3403 size_t elSize_valDims = sizeof(real_T); 3404 real_T currentSigDims = 0; 3405 int_T nRows_valDims = 0; 3406 int_T logWidth_valDims = 0; 3407 3408 for (i = 0; i < frameSize; i++) { 3409 if (++var->numHits % var->decimation) continue; 3410 var->numHits = 0; 3411 3412 if (var->rowIdx == var->data.nRows) { 3413 if (var->okayToRealloc == 1) { 3414 rt_ReallocLogVar(var, isVarDims); 3415 } else { 3416 /* Circular buffer */ 3417 var->rowIdx = 0; 3418 ++(var->wrapped); /* increment the wrap around counter */ 3419 } 3420 } 3421 3422 if(isVarDims){ 3423 currDimsPtr = (const void**) var->valDims->currSigDims; 3424 currDimsSizePtr = (const int_T*) var->valDims->currSigDimsSize; 3425 logWidth_valDims = frameData ? 1 : var->valDims->nCols; 3426 nRows_valDims = var->valDims->nRows; 3427 3428 var->strides[0] = 1; 3429 var->currStrides[0] = 1; 3430 3431 for (k = 1; k < nDims; k++){ 3432 int32_T currDimsVal=0; 3433 switch (currDimsSizePtr[k-1]) { 3434 case 1: 3435 currDimsVal = (**(((const uint8_T**) currDimsPtr)+(k-1))); 3436 break; 3437 case 2: 3438 currDimsVal = (**(((const uint16_T**) currDimsPtr)+(k-1))); 3439 break; 3440 case 4: 3441 currDimsVal = (**(((const uint32_T**) currDimsPtr)+(k-1))); 3442 break; 3443 } 3444 var->strides[k] = var->strides[k-1] * dims[k-1]; 3445 var->currStrides[k] = var->currStrides[k-1] * currDimsVal; 3446 } 3447 } 3448 3449 offset = (int_T)(elSize * var->rowIdx * logWidth); 3450 currRealRow = ((char_T*) (var->data.re)) + offset; 3451 currImagRow = (var->data.complex) ? 3452 ((char_T*) (var->data.im)) + offset : NULL; 3453 3454 /* update logging data */ 3455 for (j = 0; j < logWidth; j++) { 3456 3457 boolean_T inRange = true; 3458 int idx = j; 3459 3460 /* Check whether the currently logged value is in range or not. 3461 For fixed-size signal logging, always inRange = true; idx = j; 3462 For variable-size signal logging, use strides, coordinates 3463 and current strides to decide whether the currently logged 3464 data is in range or not and its location in the logging 3465 matrix. 3466 */ 3467 if(isVarDims){ 3468 int rem = j; 3469 idx = 0; 3470 for(k = nDims-1; k>=0; k--){ 3471 int32_T currDimsVal=0; 3472 switch (currDimsSizePtr[k]) { 3473 case 1: 3474 currDimsVal = (**(((const uint8_T**) currDimsPtr)+k)); 3475 break; 3476 case 2: 3477 currDimsVal = (**(((const uint16_T**) currDimsPtr)+k)); 3478 break; 3479 case 4: 3480 currDimsVal = (**(((const uint32_T**) currDimsPtr)+k)); 3481 break; 3482 } 3483 var->coords[k] = rem / var->strides[k]; 3484 if( var->coords[k] >= currDimsVal ){ 3485 inRange = false; 3486 break; 3487 } 3488 rem = rem - var->coords[k] * var->strides[k]; 3489 } 3490 if(inRange){ 3491 idx = var->coords[0]; 3492 for (k = 1; k < nDims; k++){ 3493 idx += var->coords[k] * var->currStrides[k]; 3494 } 3495 } 3496 } 3497 3498 if (!var->data.dataTypeConvertInfo.conversionNeeded) { 3499 /* NO conversion needed 3500 */ 3501 if (inRange) { 3502 /* If in range, fill in data */ 3503 const char *cDataPoint = cData + (i+frameSize*idx) * pointSize; 3504 3505 (void) memcpy(currRealRow, cDataPoint, elSize); 3506 currRealRow += elSize; 3507 if (var->data.complex) { 3508 (void) memcpy(currImagRow, cDataPoint + pointSize/2, elSize); 3509 currImagRow += elSize; 3510 } 3511 } else { 3512 /* If out of range, fill in NaN or 0: 3513 1) For bool, int32, uint32, int16, uint16, etc, 3514 memset to zeros; 3515 2) For fixed-point data type, NaN conversion is not 3516 allowed, memset to zeros. 3517 */ 3518 if (dTypeID == SS_DOUBLE) { 3519 (void) memcpy(currRealRow, &rtNaN, elSize); 3520 } else if (dTypeID == SS_SINGLE){ 3521 (void) memcpy(currRealRow, &rtNaNF, elSize); 3522 } else { 3523 (void) memset(currRealRow, 0, elSize); 3524 } 3525 3526 currRealRow += elSize; 3527 if (var->data.complex) { 3528 /* For imaginary part, fill in 0 */ 3529 (void) memset(currImagRow, 0, elSize); 3530 currImagRow += elSize; 3531 } 3532 } 3533 } 3534 else 3535 { 3536 /* YES conversion needed 3537 */ 3538 DTypeId dataTypeIdOriginal = 3539 var->data.dataTypeConvertInfo.dataTypeIdOriginal; 3540 int_T DpSize = (int_T)((var->data.complex) ? 3541 rt_GetSizeofComplexType(dataTypeIdOriginal) : 3542 rt_GetSizeofDataType(dataTypeIdOriginal)); 3543 3544 DTypeId dataTypeIdLoggingTo = 3545 var->data.dataTypeConvertInfo.dataTypeIdLoggingTo; 3546 3547 int bitsPerChunk = var->data.dataTypeConvertInfo.bitsPerChunk; 3548 int numOfChunk = var->data.dataTypeConvertInfo.numOfChunk; 3549 unsigned int isSigned = var->data.dataTypeConvertInfo.isSigned; 3550 3551 double fracSlope = var->data.dataTypeConvertInfo.fracSlope; 3552 int fixedExp = var->data.dataTypeConvertInfo.fixedExp; 3553 double bias = var->data.dataTypeConvertInfo.bias; 3554 3555 double curRealValue = -0.12345678987654; 3556 double curImagValue = -0.12345678987654; 3557 3558 int_T adjIndexIfComplex = (var->data.complex) ? 2 : 1; 3559 3560 if(inRange){ 3561 if(numOfChunk > 1) 3562 { 3563 /* For multiword */ 3564 const char *pInData = (const char *)(cData); 3565 int dtSize = bitsPerChunk*numOfChunk/8; 3566 pInData += ((i+frameSize*idx) * adjIndexIfComplex) * dtSize; 3567 3568 curRealValue = rt_GetDblValueFromOverSizedData(pInData, bitsPerChunk, numOfChunk, 3569 isSigned, fracSlope, fixedExp, bias); 3570 if (var->data.complex) { 3571 curImagValue = rt_GetDblValueFromOverSizedData((pInData+dtSize), bitsPerChunk, numOfChunk, 3572 isSigned, fracSlope, fixedExp, bias); 3573 } 3574 } 3575 else 3576 { 3577 /* if in range, fill in data that is converted first */ 3578 switch ( dataTypeIdOriginal ) 3579 { 3580 case SS_DOUBLE: 3581 { 3582 const real_T *pInData = (const real_T *)(cData + (i+frameSize*idx)* DpSize); 3583 3584 curRealValue = ldexp( fracSlope * (double)(*pInData), fixedExp ) + bias; 3585 if (var->data.complex) { 3586 pInData = (const real_T *)(cData + (i+frameSize*idx)* DpSize + DpSize/2); 3587 curImagValue = ldexp( fracSlope * (double)(*pInData), fixedExp ) + bias; 3588 } 3589 } 3590 break; 3591 case SS_SINGLE: 3592 { 3593 const real32_T *pInData = (const real32_T *)(cData + (i+frameSize*idx)* DpSize); 3594 3595 curRealValue = ldexp( fracSlope * (double)(*pInData), fixedExp ) + bias; 3596 if (var->data.complex) { 3597 pInData = (const real32_T *)(cData + (i+frameSize*idx)* DpSize + DpSize/2); 3598 curImagValue = ldexp( fracSlope * (double)(*pInData), fixedExp ) + bias; 3599 } 3600 } 3601 break; 3602 case SS_INT8: 3603 { 3604 const int8_T *pInData = (const int8_T *)(cData + (i+frameSize*idx)* DpSize); 3605 3606 curRealValue = ldexp( fracSlope * (double)(*pInData), fixedExp ) + bias; 3607 if (var->data.complex) { 3608 pInData = (const int8_T *)(cData + (i+frameSize*idx)* DpSize + DpSize/2); 3609 curImagValue = ldexp( fracSlope * (double)(*pInData), fixedExp ) + bias; 3610 } 3611 } 3612 break; 3613 case SS_UINT8: 3614 { 3615 const uint8_T *pInData = (const uint8_T *)(cData + (i+frameSize*idx)* DpSize); 3616 3617 curRealValue = ldexp( fracSlope * (double)(*pInData), fixedExp ) + bias; 3618 if (var->data.complex) { 3619 pInData = (const uint8_T *)(cData + (i+frameSize*idx)* DpSize + DpSize/2); 3620 curImagValue = ldexp( fracSlope * (double)(*pInData), fixedExp ) + bias; 3621 } 3622 } 3623 break; 3624 case SS_INT16: 3625 { 3626 const int16_T *pInData = (const int16_T *)(cData + (i+frameSize*idx)* DpSize); 3627 3628 curRealValue = ldexp( fracSlope * (double)(*pInData), fixedExp ) + bias; 3629 if (var->data.complex) { 3630 pInData = (const int16_T *)(cData + (i+frameSize*idx)* DpSize + DpSize/2); 3631 curImagValue = ldexp( fracSlope * (double)(*pInData), fixedExp ) + bias; 3632 } 3633 } 3634 break; 3635 case SS_UINT16: 3636 { 3637 const uint16_T *pInData = (const uint16_T *)(cData + (i+frameSize*idx)* DpSize); 3638 3639 curRealValue = ldexp( fracSlope * (double)(*pInData), fixedExp ) + bias; 3640 if (var->data.complex) { 3641 pInData = (const uint16_T *)(cData + (i+frameSize*idx)* DpSize + DpSize/2); 3642 curImagValue = ldexp( fracSlope * (double)(*pInData), fixedExp ) + bias; 3643 } 3644 } 3645 break; 3646 case SS_INT32: 3647 { 3648 const int32_T *pInData = (const int32_T *)(cData + (i+frameSize*idx)* DpSize); 3649 3650 curRealValue = ldexp( fracSlope * (double)(*pInData), fixedExp ) + bias; 3651 if (var->data.complex) { 3652 pInData = (const int32_T *)(cData + (i+frameSize*idx)* DpSize + DpSize/2); 3653 curImagValue = ldexp( fracSlope * (double)(*pInData), fixedExp ) + bias; 3654 } 3655 } 3656 break; 3657 case SS_UINT32: 3658 { 3659 const uint32_T *pInData = (const uint32_T *)(cData + (i+frameSize*idx)* DpSize); 3660 3661 curRealValue = ldexp( fracSlope * (double)(*pInData), fixedExp ) + bias; 3662 if (var->data.complex) { 3663 pInData = (const uint32_T *)(cData + (i+frameSize*idx)* DpSize + DpSize/2); 3664 curImagValue = ldexp( fracSlope * (double)(*pInData), fixedExp ) + bias; 3665 } 3666 } 3667 break; 3668 case SS_BOOLEAN: 3669 { 3670 const boolean_T *pInData = ((const boolean_T *)(cData)); 3671 3672 pInData += (i+frameSize*idx) * adjIndexIfComplex; 3673 3674 curRealValue = ldexp( fracSlope * (double)(*pInData), fixedExp ) + bias; 3675 if (var->data.complex) { 3676 curImagValue = ldexp( fracSlope * (double)(*pInData), fixedExp ) + bias; 3677 } 3678 } 3679 break; 3680 default: 3681 { 3682 /* For biglong */ 3683 const char *pInData = (const char *)(cData); 3684 int dtSize = bitsPerChunk*numOfChunk/8; 3685 pInData += ((i+frameSize*idx) * adjIndexIfComplex) * dtSize; 3686 3687 curRealValue = rt_GetDblValueFromOverSizedData(pInData, bitsPerChunk, numOfChunk, 3688 isSigned, fracSlope, fixedExp, bias); 3689 if (var->data.complex) { 3690 curImagValue = rt_GetDblValueFromOverSizedData((pInData+dtSize), bitsPerChunk, numOfChunk, 3691 isSigned, fracSlope, fixedExp, bias); 3692 } 3693 } 3694 break; 3695 } /* -- end of switch -- */ 3696 } 3697 } else { 3698 /* if out of range, just fill NaN or 0 */ 3699 if(dTypeID == SS_DOUBLE || dTypeID == SS_SINGLE){ 3700 curRealValue = ldexp( rtNaN, fixedExp ) + bias; 3701 } 3702 else{ 3703 curRealValue = ldexp( 0, fixedExp ) + bias; 3704 } 3705 if (var->data.complex) { 3706 /* fill 0 in imaginary part*/ 3707 curImagValue = ldexp( 0, fixedExp ) + bias; 3708 } 3709 } 3710 3711 switch ( dataTypeIdLoggingTo ) 3712 { 3713 case SS_DOUBLE: 3714 { 3715 *((real_T *)currRealRow) = (real_T)curRealValue; 3716 3717 if (var->data.complex) { 3718 3719 *((real_T *)currImagRow) = (real_T)curImagValue; 3720 } 3721 } 3722 break; 3723 case SS_SINGLE: 3724 { 3725 *((real32_T *)currRealRow) = (real32_T)curRealValue; 3726 3727 if (var->data.complex) { 3728 3729 *((real32_T *)currImagRow) = (real32_T)curImagValue; 3730 } 3731 } 3732 break; 3733 case SS_INT8: 3734 { 3735 *((int8_T *)currRealRow) = (int8_T)curRealValue; 3736 3737 if (var->data.complex) { 3738 3739 *((int8_T *)currImagRow) = (int8_T)curImagValue; 3740 } 3741 } 3742 break; 3743 case SS_UINT8: 3744 { 3745 *((uint8_T *)currRealRow) = (uint8_T)curRealValue; 3746 3747 if (var->data.complex) { 3748 3749 *((uint8_T *)currImagRow) = (uint8_T)curImagValue; 3750 } 3751 } 3752 break; 3753 case SS_INT16: 3754 { 3755 *((int16_T *)currRealRow) = (int16_T)curRealValue; 3756 3757 if (var->data.complex) { 3758 3759 *((int16_T *)currImagRow) = (int16_T)curImagValue; 3760 } 3761 } 3762 break; 3763 case SS_UINT16: 3764 { 3765 *((uint16_T *)currRealRow) = (uint16_T)curRealValue; 3766 3767 if (var->data.complex) { 3768 3769 *((uint16_T *)currImagRow) = (uint16_T)curImagValue; 3770 } 3771 } 3772 break; 3773 case SS_INT32: 3774 { 3775 *((int32_T *)currRealRow) = (int32_T)curRealValue; 3776 3777 if (var->data.complex) { 3778 3779 *((int32_T *)currImagRow) = (int32_T)curImagValue; 3780 } 3781 } 3782 break; 3783 case SS_UINT32: 3784 { 3785 *((uint32_T *)currRealRow) = (uint32_T)curRealValue; 3786 3787 if (var->data.complex) { 3788 3789 *((uint32_T *)currImagRow) = (uint32_T)curImagValue; 3790 } 3791 } 3792 break; 3793 case SS_BOOLEAN: 3794 { 3795 *((boolean_T *)currRealRow) = (boolean_T)(curRealValue != 0.0); 3796 3797 if (var->data.complex) { 3798 3799 *((boolean_T *)currImagRow) = (boolean_T)(curImagValue != 0.0); 3800 } 3801 } 3802 break; 3803 } /* -- end of switch -- */ 3804 3805 currRealRow += elSize; 3806 if (var->data.complex) { 3807 currImagRow += elSize; 3808 } 3809 } 3810 } 3811 3812 if(isVarDims){ /* update "valueDimensions" field */ 3813 for(j = 0; j < logWidth_valDims; j ++){ 3814 int32_T currDimsVal=0; 3815 switch (currDimsSizePtr[j]) { 3816 case 1: 3817 currDimsVal = (**(((const uint8_T**) currDimsPtr)+j)); 3818 break; 3819 case 2: 3820 currDimsVal = (**(((const uint16_T**) currDimsPtr)+j)); 3821 break; 3822 case 4: 3823 currDimsVal = (**(((const uint32_T**) currDimsPtr)+j)); 3824 break; 3825 } 3826 offset_valDims = (int_T)(elSize_valDims *( var->rowIdx + nRows_valDims * j)); 3827 currValDimsRow = ((char_T*) (var->valDims->dimsData)) + offset_valDims; 3828 3829 /* convert int_T to real_T */ 3830 currentSigDims = (real_T) currDimsVal; 3831 (void) memcpy(currValDimsRow, ¤tSigDims, elSize_valDims); 3832 currValDimsRow += elSize_valDims; 3833 } 3834 } 3835 3836 ++var->rowIdx; 3837 } 3838 3839 return; 3840 3841 } /* end rt_UpdateLogVar */ 3842 3843 BEGIN_PUBLIC 3844 #ifdef __cplusplus 3845 } 3846 #endif 3847 END_PUBLIC 3848 3849 3850 BEGIN_PUBLIC 3851 #ifdef __cplusplus 3852 extern "C" { 3853 #endif 3854 END_PUBLIC 3855 3856 /* Function: rt_UpdateStructLogVar ============================================= 3857 * Abstract: 3858 * Called to log data for a structure log variable. 3859 */ 3860 PUBLIC void rt_UpdateStructLogVar(StructLogVar *var, const real_T *t, const void *data) 3861 { 3862 LogVar *values = var->signals.values; 3863 const char_T *signal = data; 3864 boolean_T *isVarDims = var->signals.isVarDims; 3865 int i = 0; 3866 3867 /* time */ 3868 if (var->logTime) { 3869 rt_UpdateLogVar(var->time, t, false); 3870 } 3871 3872 /* signals */ 3873 while (values) { 3874 size_t elSz = values->data.elSize; 3875 3876 rt_UpdateLogVar(values, signal, isVarDims[i]); 3877 3878 if (values->data.complex) elSz *= 2; 3879 signal += elSz * values->data.nCols; 3880 3881 values = values->next; 3882 i++; 3883 } 3884 3885 } /* end rt_UpdateStructLogVar */ 3886 3887 BEGIN_PUBLIC 3888 #ifdef __cplusplus 3889 } 3890 #endif 3891 END_PUBLIC 3892 3893 3894 BEGIN_PUBLIC 3895 #ifdef __cplusplus 3896 extern "C" { 3897 #endif 3898 END_PUBLIC 3899 3900 /* Function: rt_UpdateTXYLogVars =============================================== 3901 * Abstract: 3902 * Update the T,X,Y variables that are being logged. 3903 */ 3904 PUBLIC const char_T *rt_UpdateTXYLogVars(RTWLogInfo *li, time_T *tPtr) 3905 { 3906 LogInfo *logInfo = rtliGetLogInfo(li); 3907 int_T matrixFormat = (rtliGetLogFormat(li) == 0); 3908 3909 /* time */ 3910 if (logInfo->t != NULL) { 3911 rt_UpdateLogVar(logInfo->t, tPtr, false); 3912 } 3913 3914 if (matrixFormat) { /* MATRIX_FORMAT */ 3915 /* states */ 3916 if (logInfo->x != NULL || logInfo->xFinal != NULL) { 3917 const RTWLogSignalInfo *xInfo = rtliGetLogXSignalInfo(li); 3918 LogSignalPtrsType segAddr = rtliGetLogXSignalPtrs(li); 3919 const int_T *segLengths = xInfo->numCols; 3920 int_T nSegments = xInfo->numSignals; 3921 if (logInfo->x != NULL) { 3922 rt_UpdateLogVarWithDiscontiguousData(logInfo->x, segAddr, 3923 segLengths, nSegments); 3924 } 3925 if (logInfo->xFinal != NULL) { 3926 rt_UpdateLogVarWithDiscontiguousData(logInfo->xFinal, segAddr, 3927 segLengths, nSegments); 3928 } 3929 } 3930 /* outputs */ 3931 if (logInfo->y != NULL) { 3932 LogVar **var = (LogVar**) (logInfo->y); 3933 int_T ny = logInfo->ny; 3934 int_T i; 3935 int yIdx; 3936 LogSignalPtrsType data = rtliGetLogYSignalPtrs(li); 3937 3938 for (i = 0, yIdx = 0; i < ny; i++) { 3939 if (data[i] != NULL) { 3940 /* 3941 When outputs are logged in Matrix format, 3942 no variable-size signal logging is allowed. 3943 */ 3944 rt_UpdateLogVar(var[yIdx++], data[i], false); 3945 } 3946 } 3947 } 3948 } else { /* STRUCTURE_FORMAT */ 3949 /* states */ 3950 if (logInfo->x != NULL) { 3951 int_T i; 3952 StructLogVar *var = logInfo->x; 3953 LogVar *val = var->signals.values; 3954 int_T nsig = var->signals.numSignals; 3955 LogSignalPtrsType data = rtliGetLogXSignalPtrs(li); 3956 3957 /* time */ 3958 if (var->logTime) { 3959 rt_UpdateLogVar(var->time, tPtr, false); 3960 } 3961 3962 /* signals */ 3963 for (i = 0; i < nsig; i++) { 3964 rt_UpdateLogVar(val, data[i], false); 3965 val = val->next; 3966 } 3967 } 3968 3969 /* outputs */ 3970 if (logInfo->y != NULL) { 3971 int_T ny = logInfo->ny; 3972 LogSignalPtrsType data = rtliGetLogYSignalPtrs(li); 3973 StructLogVar **var = (StructLogVar**) (logInfo->y); 3974 3975 if (ny == 1) { 3976 int_T i; 3977 int_T dataIdx; 3978 LogVar *val = var[0]->signals.values; 3979 int_T nsig = var[0]->signals.numSignals; 3980 boolean_T *isVarDims = var[0]->signals.isVarDims; 3981 3982 /* time */ 3983 if (var[0]->logTime) { 3984 rt_UpdateLogVar(var[0]->time, tPtr, false); 3985 } 3986 3987 /* signals */ 3988 for (i = 0, dataIdx = 0; i < nsig; i++) { 3989 while (data[dataIdx] == NULL) { 3990 ++dataIdx; 3991 } 3992 rt_UpdateLogVar(val, data[dataIdx], isVarDims[i]); 3993 val = val->next; 3994 ++dataIdx; 3995 } 3996 } else { 3997 int_T i; 3998 int_T dataIdx; 3999 4000 for (i = 0, dataIdx = 0; i < ny && var[i] != NULL; i++) { 4001 LogVar *val = var[i]->signals.values; 4002 boolean_T *isVarDims = var[i]->signals.isVarDims; 4003 4004 /* time */ 4005 if (var[i]->logTime) { 4006 rt_UpdateLogVar(var[i]->time, tPtr, false); 4007 } 4008 4009 /* signals */ 4010 while (data[dataIdx] == NULL) { 4011 ++dataIdx; 4012 } 4013 rt_UpdateLogVar(val, data[dataIdx], isVarDims[0]); 4014 val = val->next; 4015 ++dataIdx; 4016 } 4017 } 4018 } 4019 /* final state */ 4020 if (logInfo->xFinal != NULL) { 4021 StructLogVar *xf = logInfo->xFinal; 4022 LogVar *val = xf->signals.values; 4023 int_T nsig = xf->signals.numSignals; 4024 int_T i; 4025 4026 /* time */ 4027 if (xf->logTime) { 4028 rt_UpdateLogVar(xf->time, tPtr, false); 4029 } 4030 4031 /* signals */ 4032 for (i = 0; i < nsig; i++) { 4033 LogSignalPtrsType data = rtliGetLogXSignalPtrs(li); 4034 4035 rt_UpdateLogVar(val, data[i], false); 4036 val = val->next; 4037 } 4038 } 4039 } 4040 return(NULL); 4041 4042 } /* end rt_UpdateTXYLogVars */ 4043 4044 BEGIN_PUBLIC 4045 #ifdef __cplusplus 4046 } 4047 #endif 4048 END_PUBLIC 4049 4050 4051 BEGIN_PUBLIC 4052 #ifdef __cplusplus 4053 extern "C" { 4054 #endif 4055 END_PUBLIC 4056 4057 /* Function: rt_UpdateSigLogVars =============================================== 4058 * Abstract: 4059 * Update the Signal Logging testpoint variables that are being logged. 4060 * 4061 */ 4062 PUBLIC void rt_UpdateSigLogVars(RTWLogInfo *li, time_T *tPtr) 4063 { 4064 LogInfo *logInfo = rtliGetLogInfo(li); 4065 4066 if (logInfo->sl != NULL) { 4067 int_T i; 4068 StructLogVar *var = logInfo->sl; 4069 LogVar *val = var->signals.values; 4070 int_T nsig = var->signals.numSignals; 4071 LogSignalPtrsType data = rtliGetSigLogSignalPtrs(li); 4072 4073 /* time */ 4074 if (var->logTime) { 4075 rt_UpdateLogVar(var->time, tPtr, false); 4076 } 4077 4078 /* signals */ 4079 for (i = 0; i < nsig; i++) { 4080 /* currently, SigLog doesn't support variable-size signals */ 4081 rt_UpdateLogVar(val, data[i], false); 4082 val = val->next; 4083 } 4084 } 4085 4086 } /* end rt_UpdateSigLogVars */ 4087 4088 BEGIN_PUBLIC 4089 #ifdef __cplusplus 4090 } 4091 #endif 4092 END_PUBLIC 4093 4094 4095 BEGIN_PUBLIC 4096 #ifdef __cplusplus 4097 extern "C" { 4098 #endif 4099 END_PUBLIC 4100 4101 /* Function: rt_StopDataLoggingForRaccel ======================================= 4102 * Abstract: 4103 * Write logged data to model.mat and free memory. 4104 */ 4105 PUBLIC void rt_StopDataLoggingForRaccel(const char_T *file, RTWLogInfo *li, int verbose) 4106 { 4107 FILE *fptr; 4108 LogInfo *logInfo = (LogInfo*) rtliGetLogInfo(li); 4109 LogVar *var = logInfo->logVarsList; 4110 StructLogVar *svar = logInfo->structLogVarsList; 4111 4112 boolean_T emptyFile = 1; /* assume */ 4113 boolean_T errFlag = 0; 4114 const char_T *msg; 4115 4116 /******************************* 4117 * Create MAT file with header * 4118 *******************************/ 4119 if ((fptr=fopen(file,"w+b")) == NULL) { 4120 (void)fprintf(stderr,"*** Error opening %s",file); 4121 goto EXIT_POINT; 4122 } 4123 if (rt_WriteMat5FileHeader(fptr)) { 4124 (void)fprintf(stderr,"*** Error writing to %s",file); 4125 goto EXIT_POINT; 4126 } 4127 4128 /************************************************** 4129 * First log all the variables in the LogVar list * 4130 **************************************************/ 4131 while (var != NULL) { 4132 if ( (msg = rt_FixupLogVar(var,verbose)) != NULL ) { 4133 (void)fprintf(stderr,"*** Error writing %s due to: %s\n",file,msg); 4134 errFlag = 1; 4135 break; 4136 } 4137 if (var->nDataPoints > 0) { 4138 MatItem item; 4139 4140 item.type = matMATRIX; 4141 item.nbytes = 0; /* not yet known */ 4142 item.data = &(var->data); 4143 if (rt_WriteItemToMatFile(fptr, &item, MATRIX_ITEM)) { 4144 (void)fprintf(stderr,"*** Error writing log variable %s to " 4145 "file %s",var->data.name, file); 4146 errFlag = 1; 4147 break; 4148 } 4149 emptyFile = 0; 4150 } 4151 var = var->next; 4152 } 4153 /* free up some memory by destroying the log var list here */ 4154 rt_DestroyLogVar(logInfo->logVarsList); 4155 logInfo->logVarsList = NULL; 4156 4157 /******************************************************* 4158 * Next log all the variables in the StrcutLogVar list * 4159 *******************************************************/ 4160 while (svar != NULL) { 4161 MatItem item; 4162 4163 if (svar->logTime) { 4164 var = svar->time; 4165 if ( (msg = rt_FixupLogVar(var,verbose)) != NULL ) { 4166 (void)fprintf(stderr, "*** Error writing %s due to: %s\n", 4167 file, msg); 4168 errFlag = 1; 4169 break; 4170 } 4171 } 4172 4173 var = svar->signals.values; 4174 while (var) { 4175 if ( (msg = rt_FixupLogVar(var,verbose)) != NULL ) { 4176 (void)fprintf(stderr, "*** Error writing %s due to: %s\n", 4177 file, msg); 4178 errFlag = 1; 4179 break; 4180 } 4181 var = var->next; 4182 } 4183 4184 item.type = matMATRIX; 4185 item.nbytes = 0; /* not yet known */ 4186 item.data = svar; 4187 4188 if (rt_WriteItemToMatFile(fptr, &item, STRUCT_LOG_VAR_ITEM)) { 4189 (void)fprintf(stderr,"*** Error writing structure log variable " 4190 "%s to file %s",svar->name, file); 4191 errFlag = 1; 4192 break; 4193 } 4194 emptyFile = 0; 4195 4196 svar = svar->next; 4197 } 4198 4199 /****************** 4200 * Close the file * 4201 ******************/ 4202 (void)fclose(fptr); 4203 if (emptyFile || errFlag) { 4204 (void)remove(file); 4205 } else { 4206 if( verbose ) { 4207 (void)printf("** created %s **\n\n", file); 4208 } 4209 } 4210 4211 EXIT_POINT: 4212 4213 /**************** 4214 * free logInfo * 4215 ****************/ 4216 rt_DestroyLogVar(logInfo->logVarsList); 4217 logInfo->logVarsList = NULL; 4218 rt_DestroyStructLogVar(logInfo->structLogVarsList); 4219 logInfo->structLogVarsList = NULL; 4220 FREE(logInfo); 4221 rtliSetLogInfo(li,NULL); 4222 4223 } /* end rt_StopDataLoggingForRaccel */ 4224 4225 BEGIN_PUBLIC 4226 #ifdef __cplusplus 4227 } 4228 #endif 4229 END_PUBLIC 4230 4231 4232 BEGIN_PUBLIC 4233 #ifdef __cplusplus 4234 extern "C" { 4235 #endif 4236 END_PUBLIC 4237 4238 /* Function: rt_StopDataLogging ================================================ 4239 * Abstract: 4240 * Write logged data to model.mat and free memory. 4241 */ 4242 PUBLIC void rt_StopDataLogging(const char_T *file, RTWLogInfo *li) 4243 { 4244 rt_StopDataLoggingForRaccel(file,li,1); 4245 4246 } /* end rt_StopDataLogging */ 4247 4248 BEGIN_PUBLIC 4249 #ifdef __cplusplus 4250 } 4251 #endif 4252 END_PUBLIC 4253 4254 BEGIN_PUBLIC 4255 #else /*!defined(MAT_FILE) || (defined(MAT_FILE) && MAT_FILE == 1)*/ 4256 4257 #define rt_StartDataLogging(li, finalTime, stepSize, errStatus) NULL /* do nothing */ 4258 #define rt_UpdateTXYLogVars(li, tPtr) NULL /* do nothing */ 4259 #define rt_UpdateSigLogVars(li, tPtr); /* do nothing */ 4260 #define rt_StopDataLogging(file, li); /* do nothing */ 4261 4262 #endif /*!defined(MAT_FILE) || (defined(MAT_FILE) && MAT_FILE == 1)*/ 4263 END_PUBLIC 4264 4265 4266 /* [eof] rt_logging.c */ 4267 |