📄 cm.c
字号:
(byte_index > ((ckt->CKTnumStates - 1) * sizeof(double)) ) ) { g_mif_info.errmsg = "ERROR - cm_analog_converge() - Argument must be in state vector 0\n"; return(MIF_ERROR); } /* Scan the conv array in the instance struct to see if already registered */ /* If so, do nothing, just return */ for(i = 0; i < here->num_conv; i++) { if(here->conv[i].byte_index == byte_index) return(MIF_OK); } /* Allocate space in instance struct for this conv descriptor */ if(here->num_conv == 0) { here->num_conv = 1; here->conv = (void *) MALLOC(sizeof(Mif_Conv_t)); } else { here->num_conv++; here->conv = (void *) REALLOC(here->conv, here->num_conv * sizeof(Mif_Conv_t)); } /* Fill in the conv descriptor data */ conv = &(here->conv[here->num_conv - 1]); conv->byte_index = byte_index; conv->last_value = 1.0e30; /* There should be a better way ... */ return(MIF_OK);}/*cm_message_get_errmsg()This function returns the address of an error message string setby a call to some code model support function.*/char *cm_message_get_errmsg(void){ return(g_mif_info.errmsg);}/*cm_analog_set_temp_bkpt()This function is called by a code model C function to set atemporary breakpoint. These temporary breakpoints remain ineffect only until the next timestep is taken. A temporarybreakpoint added with a time less than the current time, butgreater than the last successful timestep causes the simulator toabandon the current timestep and decrease the timestep to hit thebreakpoint. A temporary breakpoint with a time greater than thecurrent time causes the simulator to make the breakpoint the nexttimepoint if the next timestep would produce a time greater thanthat of the breakpoint.*/int cm_analog_set_temp_bkpt( double time) /* The time of the breakpoint to be set */{ CKTcircuit *ckt; /* Get the address of the ckt and instance structs from g_mif_info */ ckt = g_mif_info.ckt; /* Make sure breakpoint is not prior to last accepted timepoint */ if(time < ((ckt->CKTtime - ckt->CKTdelta) + ckt->CKTminBreak)) { g_mif_info.errmsg = "ERROR - cm_analog_set_temp_bkpt() - Time < last accepted timepoint\n"; return(MIF_ERROR); } /* If too close to a permanent breakpoint or the current time, discard it */ if( (fabs(time - ckt->CKTbreaks[0]) < ckt->CKTminBreak) || (fabs(time - ckt->CKTbreaks[1]) < ckt->CKTminBreak) || (fabs(time - ckt->CKTtime) < ckt->CKTminBreak) ) return(MIF_OK); /* If < current dynamic breakpoint, make it the current breakpoint */ if( time < g_mif_info.breakpoint.current) g_mif_info.breakpoint.current = time; return(MIF_OK);}/*cm_analog_set_perm_bkpt()This function is called by a code model C function to set apermanent breakpoint. These permanent breakpoints remain ineffect from the time they are introduced until the simulationtime equals or exceeds the breakpoint time. A permanentbreakpoint added with a time less than the current time, butgreater than the last successful timestep causes the simulator toabandon the current timestep and decrease the timestep to hit thebreakpoint. A permanent breakpoint with a time greater than thecurrent time causes the simulator to make the breakpoint the nexttimepoint if the next timestep would produce a time greater thanthat of the breakpoint.*/int cm_analog_set_perm_bkpt( double time) /* The time of the breakpoint to be set */{ CKTcircuit *ckt; /* Get the address of the ckt and instance structs from g_mif_info */ ckt = g_mif_info.ckt; /* Call cm_analog_set_temp_bkpt() to force backup if less than current time */ if(time < (ckt->CKTtime + ckt->CKTminBreak)) return(cm_analog_set_temp_bkpt(time)); else CKTsetBreak(ckt,time); return(MIF_OK);}/*cm_analog_ramp_factor()This function returns the current value of the ramp factorassociated with the ``ramptime'' option. For this optionto work best, models with analog outputs that may be non-zero attime zero should call this function and scale their outputsand partials by the ramp factor.*/double cm_analog_ramp_factor(void){ CKTcircuit *ckt; /* Get the address of the ckt and instance structs from g_mif_info */ ckt = g_mif_info.ckt; /* if ramptime == 0.0, no ramptime option given, so return 1.0 */ /* this is the most common case, so it goes first */ if(ckt->enh->ramp.ramptime == 0.0) return(1.0); /* else if not transient analysis, return 1.0 */ else if( (!(ckt->CKTmode & MODETRANOP)) && (!(ckt->CKTmode & MODETRAN)) ) return(1.0); /* else if time >= ramptime, return 1.0 */ else if(ckt->CKTtime >= ckt->enh->ramp.ramptime) return(1.0); /* else time < end of ramp, so compute and return factor based on time */ else return(ckt->CKTtime / ckt->enh->ramp.ramptime);}/* ************************************************************ *//* * Copyright (c) 1985 Thomas L. Quarles * * This is a modified version of the function NIintegrate() * * Modifications are Copyright 1991 Georgia Tech Research Institute * */static void cm_static_integrate(int byte_index, double integrand, double *integral, double *partial){ CKTcircuit *ckt; double intgr[7]; double cur=0; double *double_ptr; double ceq; double geq; char *char_ptr; int i; /* Get the address of the ckt struct from g_mif_info */ ckt = g_mif_info.ckt; /* Get integral values from current and previous timesteps */ for(i = 0; i <= ckt->CKTorder; i++) { char_ptr = (char *) ckt->CKTstates[i]; char_ptr += byte_index; double_ptr = (double *) char_ptr; intgr[i] = *double_ptr; } /* Do what SPICE3C1 does for its implicit integration */ switch(ckt->CKTintegrateMethod) { case TRAPEZOIDAL: switch(ckt->CKTorder) { case 1: cur = ckt->CKTag[1] * intgr[1]; break; case 2: /* WARNING - This code needs to be redone. */ /* The correct code should rely on one previous value */ /* of cur as done in NIintegrate() */ cur = -0.5 * ckt->CKTag[0] * intgr[1]; break; } break; case GEAR: cur = 0.0; switch(ckt->CKTorder) { case 6: cur += ckt->CKTag[6] * intgr[6]; /* fall through */ case 5: cur += ckt->CKTag[5] * intgr[5]; /* fall through */ case 4: cur += ckt->CKTag[4] * intgr[4]; /* fall through */ case 3: cur += ckt->CKTag[3] * intgr[3]; /* fall through */ case 2: cur += ckt->CKTag[2] * intgr[2]; /* fall through */ case 1: cur += ckt->CKTag[1] * intgr[1]; break; } break; } ceq = cur; geq = ckt->CKTag[0]; /* WARNING: Take this out when the case 2: above is fixed */ if((ckt->CKTintegrateMethod == TRAPEZOIDAL) && (ckt->CKTorder == 2)) geq *= 0.5; /* The following code is equivalent to */ /* the solution of one matrix iteration to produce the */ /* integral value. */ *integral = (integrand - ceq) / geq; *partial = 1.0 / geq;}/*cm_analog_not_converged()This function tells the simulator not to allow the currentiteration to be the final iteration. It is called whena code model performs internal limiting on one or more ofits inputs to assist convergence.*/void cm_analog_not_converged(void){ (g_mif_info.ckt->CKTnoncon)++;}/*cm_message_send()This function prints a message output from a code model, prependingthe instance name.*/int cm_message_send( char *msg) /* The message to output. */{ MIFinstance *here; /* Get the address of the instance struct from g_mif_info */ here = g_mif_info.instance; /* Print the name of the instance and the message */ printf("\nInstance: %s Message: %s\n", (char *) here->MIFname, msg); return(0);}/*cm_analog_auto_partial()This function tells the simulator to automatically computeapproximations of partial derivatives of analog outputswith respect to analog inputs. When called from a codemodel, it sets a flag in the g_mif_info structurewhich tells function MIFload() and it's associatedMIFauto_partial() function to perform the necessarycalculations.*/void cm_analog_auto_partial(void){ g_mif_info.auto_partial.local = MIF_TRUE;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -