Browse Source

Add STATIC_VAR_TABLE locdata

Add CALLBACK cm_d_pwm_callback
Reserve memory for x, y arrays only once during INIT
pre-master-46
Holger Vogt 3 years ago
parent
commit
e47049f31a
  1. 117
      src/xspice/icm/digital/d_pwm/cfunc.mod
  2. 6
      src/xspice/icm/digital/d_pwm/ifspec.ifs

117
src/xspice/icm/digital/d_pwm/cfunc.mod

@ -19,7 +19,7 @@ MODIFICATIONS
23 Aug 1991 Jeffrey P. Murray 23 Aug 1991 Jeffrey P. Murray
30 Sep 1991 Jeffrey P. Murray 30 Sep 1991 Jeffrey P. Murray
06 Oct 2022 Holger Vogt
SUMMARY SUMMARY
@ -69,7 +69,10 @@ NON-STANDARD FEATURES
/*=== LOCAL VARIABLES & TYPEDEFS =======*/ /*=== LOCAL VARIABLES & TYPEDEFS =======*/
typedef struct {
double *x;
double *y;
} Local_Data_t;
/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ /*=== FUNCTION PROTOTYPE DEFINITIONS ===*/
@ -120,6 +123,27 @@ NON-STANDARD FEATURES
==============================================================================*/ ==============================================================================*/
static void cm_d_pwm_callback(ARGS,
Mif_Callback_Reason_t reason)
{
switch (reason) {
case MIF_CB_DESTROY: {
Local_Data_t *loc = STATIC_VAR(locdata);
if (loc) {
if (loc->x)
free(loc->x);
if(loc->y)
free(loc->y);
free(loc);
STATIC_VAR(locdata) = loc = NULL;
}
break;
} /* end of case MIF_CB_DESTROY */
} /* end of switch over reason being called */
} /* end of function cm_d_pwm_callback */
/*=== CM_D_PWM ROUTINE ===*/ /*=== CM_D_PWM ROUTINE ===*/
/************************************************************* /*************************************************************
@ -179,15 +203,12 @@ void cm_d_pwm(ARGS)
slope; /* slope value...used to extrapolate slope; /* slope value...used to extrapolate
freq values past endpoints. */ freq values past endpoints. */
int i, /* generic loop counter index */ int i, /* generic loop counter index */
cntl_size, /* control array size */ cntl_size, /* control array size */
dc_size; /* duty cycle array size */ dc_size; /* duty cycle array size */
Local_Data_t *loc; /* Pointer to local static data, not to be included
in the state vector (save memory!) */
/**** Retrieve frequently used parameters... ****/ /**** Retrieve frequently used parameters... ****/
@ -195,7 +216,6 @@ void cm_d_pwm(ARGS)
dc_size = PARAM_SIZE(dc_array); dc_size = PARAM_SIZE(dc_array);
frequency = PARAM(frequency); frequency = PARAM(frequency);
/* check and make sure that the control array is the /* check and make sure that the control array is the
same size as the frequency array */ same size as the frequency array */
@ -204,10 +224,8 @@ void cm_d_pwm(ARGS)
return; return;
} }
if (INIT) { /*** Test for INIT == TRUE. If so, allocate storage, etc. ***/ if (INIT) { /*** Test for INIT == TRUE. If so, allocate storage, etc. ***/
/* Allocate storage for internal variables */ /* Allocate storage for internal variables */
cm_analog_alloc(0, sizeof(double)); cm_analog_alloc(0, sizeof(double));
cm_analog_alloc(1, sizeof(double)); cm_analog_alloc(1, sizeof(double));
@ -220,15 +238,35 @@ void cm_d_pwm(ARGS)
t3 = (double *) cm_analog_get_ptr(2,0); t3 = (double *) cm_analog_get_ptr(2,0);
/*** allocate static storage for *loc ***/
STATIC_VAR (locdata) = calloc (1 , sizeof ( Local_Data_t ));
loc = STATIC_VAR (locdata);
CALLBACK = cm_d_pwm_callback;
x = loc->x = (double *) calloc((size_t) cntl_size, sizeof(double));
if (!x) {
cm_message_send(d_pwm_allocation_error);
return;
}
y = loc->y = (double *) calloc((size_t) cntl_size, sizeof(double));
if (!y) {
cm_message_send(d_pwm_allocation_error);
if(x)
free(x);
return;
}
/* Retrieve x and y values. */
for (i=0; i<cntl_size; i++) {
x[i] = PARAM(cntl_array[i]);
y[i] = PARAM(dc_array[i]);
}
} }
else { /*** This is not an initialization pass...retrieve storage else { /*** This is not an initialization pass...retrieve storage
addresses and calculate new outputs, if required. ***/ addresses and calculate new outputs, if required. ***/
/** Retrieve previous values... **/ /** Retrieve previous values... **/
/* assign internal variables */ /* assign internal variables */
phase = (double *) cm_analog_get_ptr(0,0); phase = (double *) cm_analog_get_ptr(0,0);
phase_old = (double *) cm_analog_get_ptr(0,1); phase_old = (double *) cm_analog_get_ptr(0,1);
@ -239,9 +277,6 @@ void cm_d_pwm(ARGS)
} }
switch (CALL_TYPE) { switch (CALL_TYPE) {
case ANALOG: /** analog call **/ case ANALOG: /** analog call **/
@ -250,9 +285,7 @@ void cm_d_pwm(ARGS)
if ( AC == ANALYSIS ) { /* this model does not function if ( AC == ANALYSIS ) { /* this model does not function
in AC analysis mode. */ in AC analysis mode. */
return; return;
} }
else { else {
@ -265,38 +298,17 @@ void cm_d_pwm(ARGS)
} }
*phase = *phase / 360.0; *phase = *phase / 360.0;
/* set phase value to init_phase */ /* set phase value to init_phase */
*phase_old = *phase; *phase_old = *phase;
/* preset time values to harmless values... */ /* preset time values to harmless values... */
*t1 = -1; *t1 = -1;
*t3 = -1; *t3 = -1;
}
/* Allocate storage for breakpoint domain & duty cycle range values */
x = (double *) calloc((size_t) cntl_size, sizeof(double));
if (!x) {
cm_message_send(d_pwm_allocation_error);
return;
}
y = (double *) calloc((size_t) dc_size, sizeof(double));
if (!y) {
cm_message_send(d_pwm_allocation_error);
if(x) free(x);
return;
} }
/* Retrieve x and y values. */
for (i=0; i<cntl_size; i++) {
x[i] = PARAM(cntl_array[i]);
y[i] = PARAM(dc_array[i]);
}
loc = STATIC_VAR (locdata);
x = loc->x;
y = loc->y;
/* Retrieve cntl_input value. */ /* Retrieve cntl_input value. */
cntl_input = INPUT(cntl_in); cntl_input = INPUT(cntl_in);
@ -346,7 +358,6 @@ void cm_d_pwm(ARGS)
// cm_message_send(d_pwm_positive_dc_error); // cm_message_send(d_pwm_positive_dc_error);
} }
/* calculate the instantaneous phase */ /* calculate the instantaneous phase */
*phase = *phase_old + frequency * (TIME - T(1)); *phase = *phase_old + frequency * (TIME - T(1));
@ -354,7 +365,6 @@ void cm_d_pwm(ARGS)
the period */ the period */
dphase = *phase_old - floor(*phase_old); dphase = *phase_old - floor(*phase_old);
/* Calculate the time variables and the output value /* Calculate the time variables and the output value
for this iteration */ for this iteration */
@ -365,8 +375,6 @@ void cm_d_pwm(ARGS)
if(TIME < *t3) { if(TIME < *t3) {
cm_event_queue(*t3); cm_event_queue(*t3);
} }
} }
else else
@ -380,7 +388,6 @@ void cm_d_pwm(ARGS)
if(TIME < *t1) { if(TIME < *t1) {
cm_event_queue(*t1); cm_event_queue(*t1);
} }
} }
else { else {
@ -395,23 +402,12 @@ void cm_d_pwm(ARGS)
} }
*t3 = T(1) + (1 - dphase)/frequency; *t3 = T(1) + (1 - dphase)/frequency;
} }
if(x) free(x);
if(y) free(y);
} }
break; break;
case EVENT: /** discrete call...lots to do **/ case EVENT: /** discrete call...lots to do **/
test_double = TIME; test_double = TIME;
if ( 0.0 == TIME ) { /* DC analysis...preset values, if ( 0.0 == TIME ) { /* DC analysis...preset values,
@ -424,7 +420,6 @@ void cm_d_pwm(ARGS)
} }
*phase = *phase / 360.0; *phase = *phase / 360.0;
/* set phase value to init_phase */ /* set phase value to init_phase */
*phase_old = *phase; *phase_old = *phase;
@ -433,16 +428,12 @@ void cm_d_pwm(ARGS)
*t3 = -1; *t3 = -1;
} }
/* Calculate the time variables and the output value /* Calculate the time variables and the output value
for this iteration */ for this iteration */
/* Output is always set to STRONG */ /* Output is always set to STRONG */
OUTPUT_STRENGTH(out) = STRONG; OUTPUT_STRENGTH(out) = STRONG;
if( *t1 == TIME ) { /* rising edge */ if( *t1 == TIME ) { /* rising edge */
OUTPUT_STATE(out) = ONE; OUTPUT_STATE(out) = ONE;
@ -471,9 +462,7 @@ void cm_d_pwm(ARGS)
} }
} }
} }
break; break;
} }
} }

6
src/xspice/icm/digital/d_pwm/ifspec.ifs

@ -75,3 +75,9 @@ Vector: no no
Vector_Bounds: - - Vector_Bounds: - -
Null_Allowed: yes yes Null_Allowed: yes yes
STATIC_VAR_TABLE:
Static_Var_Name: locdata
Description: "local static data"
Data_Type: pointer
Loading…
Cancel
Save