2 changed files with 263 additions and 273 deletions
@ -1,267 +1,263 @@ |
|||||
/* =========================================================================== |
|
||||
FILE CMevt.c |
|
||||
|
|
||||
MEMBER OF process XSPICE |
|
||||
|
|
||||
Copyright 1991 |
|
||||
Georgia Tech Research Corporation |
|
||||
Atlanta, Georgia 30332 |
|
||||
All Rights Reserved |
|
||||
|
|
||||
PROJECT A-8503 |
|
||||
|
|
||||
AUTHORS |
|
||||
|
|
||||
9/12/91 Bill Kuhn |
|
||||
|
|
||||
MODIFICATIONS |
|
||||
|
|
||||
<date> <person name> <nature of modifications> |
|
||||
|
|
||||
SUMMARY |
|
||||
|
|
||||
This file contains functions callable from user code models |
|
||||
that are associated with the event-driven algorithm. |
|
||||
|
|
||||
INTERFACES |
|
||||
|
|
||||
cm_event_alloc() |
|
||||
cm_event_get_ptr() |
|
||||
cm_event_queue() |
|
||||
|
|
||||
REFERENCED FILES |
|
||||
|
|
||||
None. |
|
||||
|
|
||||
NON-STANDARD FEATURES |
|
||||
|
|
||||
None. |
|
||||
|
|
||||
=========================================================================== */ |
|
||||
|
|
||||
#include "ngspice.h" |
|
||||
#include "cktdefs.h" |
|
||||
//#include "util.h" |
|
||||
|
|
||||
#include "cm.h" |
|
||||
#include "mif.h" |
|
||||
#include "evt.h" |
|
||||
|
|
||||
#include "evtproto.h" |
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
/* |
|
||||
cm_event_alloc() |
|
||||
|
|
||||
This function is called from code model C functions to allocate |
|
||||
state storage for a particular event-driven |
|
||||
instance. It is similar to the |
|
||||
function cm_analog_alloc() used by analog models, but allocates states |
|
||||
that are rotated during event-driven 'timesteps' instead of analog |
|
||||
timesteps. |
|
||||
*/ |
|
||||
|
|
||||
|
|
||||
void *cm_event_alloc( |
|
||||
int tag, /* The user-specified tag for the memory block */ |
|
||||
int bytes) /* The number of bytes to be allocated */ |
|
||||
{ |
|
||||
|
|
||||
int inst_index; |
|
||||
int num_tags; |
|
||||
|
|
||||
MIFinstance *here; |
|
||||
CKTcircuit *ckt; |
|
||||
|
|
||||
void *ptr; |
|
||||
|
|
||||
Evt_State_Desc_t **desc_ptr; |
|
||||
Evt_State_Desc_t *desc; |
|
||||
|
|
||||
Evt_State_Data_t *state_data; |
|
||||
Evt_State_t *state; |
|
||||
|
|
||||
|
|
||||
/* Get the address of the ckt and instance structs from g_mif_info */ |
|
||||
here = g_mif_info.instance; |
|
||||
ckt = g_mif_info.ckt; |
|
||||
|
|
||||
|
|
||||
/* If not initialization pass, return error */ |
|
||||
if(here->initialized) { |
|
||||
g_mif_info.errmsg = |
|
||||
"ERROR - cm_event_alloc() - Cannot alloc when not initialization pass\n"; |
|
||||
return(NULL); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
/* Get pointers for fast access */ |
|
||||
inst_index = here->inst_index; |
|
||||
state_data = ckt->evt->data.state; |
|
||||
|
|
||||
|
|
||||
/* Scan state descriptor list to determine if tag is present and to */ |
|
||||
/* find the end of the list. Report error if duplicate tag */ |
|
||||
desc_ptr = &(state_data->desc[inst_index]); |
|
||||
desc = *desc_ptr; |
|
||||
num_tags = 1; |
|
||||
while(desc) { |
|
||||
if(desc->tag == tag) { |
|
||||
g_mif_info.errmsg = |
|
||||
"ERROR - cm_event_alloc() - Duplicate tag\n"; |
|
||||
return(NULL); |
|
||||
} |
|
||||
desc_ptr = &(desc->next); |
|
||||
desc = *desc_ptr; |
|
||||
num_tags++; |
|
||||
} |
|
||||
|
|
||||
/* Create a new state description structure at end of list */ |
|
||||
/* and fill in the data and update the total size */ |
|
||||
*desc_ptr = (void *) MALLOC(sizeof(Evt_State_Desc_t)); |
|
||||
desc = *desc_ptr; |
|
||||
desc->tag = tag; |
|
||||
desc->size = bytes; |
|
||||
desc->offset = state_data->total_size[inst_index]; |
|
||||
state_data->total_size[inst_index] += bytes; |
|
||||
|
|
||||
/* Create a new state structure if list starting at head is null */ |
|
||||
state = state_data->head[inst_index]; |
|
||||
if(state == NULL) { |
|
||||
state = (void *) MALLOC(sizeof(Evt_State_t)); |
|
||||
state_data->head[inst_index] = state; |
|
||||
} |
|
||||
|
|
||||
/* Create or enlarge the block and set the time */ |
|
||||
if(num_tags == 1) |
|
||||
state->block = MALLOC(state_data->total_size[inst_index]); |
|
||||
else |
|
||||
state->block = REALLOC(state->block, |
|
||||
state_data->total_size[inst_index]); |
|
||||
|
|
||||
state->step = g_mif_info.circuit.evt_step; |
|
||||
|
|
||||
|
|
||||
/* Return allocated memory */ |
|
||||
ptr = ((char *)state->block) + desc->offset; |
|
||||
return(ptr); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
/* |
|
||||
cm_event_get_ptr() |
|
||||
|
|
||||
This function is called from code model C functions to return a |
|
||||
pointer to state storage allocated with cm_event_alloc(). A tag |
|
||||
specified in its argument list is used to locate the state in |
|
||||
question. A second argument specifies whether the desired state |
|
||||
is for the current timestep or from a preceding timestep. The |
|
||||
location of the state in memory is then computed and returned. |
|
||||
*/ |
|
||||
|
|
||||
|
|
||||
void *cm_event_get_ptr( |
|
||||
int tag, /* The user-specified tag for the memory block */ |
|
||||
int timepoint) /* The timepoint - 0=current, 1=previous */ |
|
||||
{ |
|
||||
|
|
||||
int i; |
|
||||
int inst_index; |
|
||||
|
|
||||
MIFinstance *here; |
|
||||
CKTcircuit *ckt; |
|
||||
|
|
||||
void *ptr; |
|
||||
|
|
||||
Evt_State_Desc_t *desc; |
|
||||
|
|
||||
Evt_State_Data_t *state_data; |
|
||||
Evt_State_t *state; |
|
||||
|
|
||||
|
|
||||
/* Get the address of the ckt and instance structs from g_mif_info */ |
|
||||
here = g_mif_info.instance; |
|
||||
ckt = g_mif_info.ckt; |
|
||||
|
|
||||
|
|
||||
/* If initialization pass, return error */ |
|
||||
if((! here->initialized) && (timepoint > 0)) { |
|
||||
g_mif_info.errmsg = |
|
||||
"ERROR - cm_event_get_ptr() - Cannot get_ptr(tag,1) during initialization pass\n"; |
|
||||
return(NULL); |
|
||||
} |
|
||||
|
|
||||
/* Get pointers for fast access */ |
|
||||
inst_index = here->inst_index; |
|
||||
state_data = ckt->evt->data.state; |
|
||||
|
|
||||
/* Scan state descriptor list to find the descriptor for this tag. */ |
|
||||
/* Report error if tag not found */ |
|
||||
desc = state_data->desc[inst_index]; |
|
||||
while(desc) { |
|
||||
if(desc->tag == tag) |
|
||||
break; |
|
||||
desc = desc->next; |
|
||||
} |
|
||||
|
|
||||
if(desc == NULL) { |
|
||||
g_mif_info.errmsg = |
|
||||
"ERROR - cm_event_get_ptr() - Specified tag not found\n"; |
|
||||
return(NULL); |
|
||||
} |
|
||||
|
|
||||
/* Get the state pointer from the current array */ |
|
||||
state = *(state_data->tail[inst_index]); |
|
||||
|
|
||||
/* Backup the specified number of timesteps */ |
|
||||
for(i = 0; i < timepoint; i++) |
|
||||
if(state->prev) |
|
||||
state = state->prev; |
|
||||
|
|
||||
/* Return pointer */ |
|
||||
ptr = ((char *) state->block) + desc->offset; |
|
||||
return(ptr); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
/* |
|
||||
cm_event_queue() |
|
||||
|
|
||||
This function queues an event for an instance participating |
|
||||
in the event-driven algorithm. |
|
||||
*/ |
|
||||
|
|
||||
|
|
||||
int cm_event_queue( |
|
||||
double time) /* The time of the event to be queued */ |
|
||||
{ |
|
||||
|
|
||||
MIFinstance *here; |
|
||||
CKTcircuit *ckt; |
|
||||
|
|
||||
|
|
||||
/* Get the address of the ckt and instance structs from g_mif_info */ |
|
||||
here = g_mif_info.instance; |
|
||||
ckt = g_mif_info.ckt; |
|
||||
|
|
||||
/* If breakpoint time <= current event time, return error */ |
|
||||
if(time <= g_mif_info.circuit.evt_step) { |
|
||||
g_mif_info.errmsg = |
|
||||
"ERROR - cm_event_queue() - Event time cannot be <= current time\n"; |
|
||||
return(MIF_ERROR); |
|
||||
} |
|
||||
|
|
||||
/* Add the event time to the inst queue */ |
|
||||
EVTqueue_inst(ckt, here->inst_index, g_mif_info.circuit.evt_step, |
|
||||
time); |
|
||||
|
|
||||
return(MIF_OK); |
|
||||
} |
|
||||
|
/* =========================================================================== |
||||
|
FILE CMevt.c |
||||
|
|
||||
|
MEMBER OF process XSPICE |
||||
|
|
||||
|
Copyright 1991 |
||||
|
Georgia Tech Research Corporation |
||||
|
Atlanta, Georgia 30332 |
||||
|
All Rights Reserved |
||||
|
|
||||
|
PROJECT A-8503 |
||||
|
|
||||
|
AUTHORS |
||||
|
|
||||
|
9/12/91 Bill Kuhn |
||||
|
|
||||
|
MODIFICATIONS |
||||
|
|
||||
|
<date> <person name> <nature of modifications> |
||||
|
|
||||
|
SUMMARY |
||||
|
|
||||
|
This file contains functions callable from user code models |
||||
|
that are associated with the event-driven algorithm. |
||||
|
|
||||
|
INTERFACES |
||||
|
|
||||
|
cm_event_alloc() |
||||
|
cm_event_get_ptr() |
||||
|
cm_event_queue() |
||||
|
|
||||
|
REFERENCED FILES |
||||
|
|
||||
|
None. |
||||
|
|
||||
|
NON-STANDARD FEATURES |
||||
|
|
||||
|
None. |
||||
|
|
||||
|
=========================================================================== */ |
||||
|
|
||||
|
#include "ngspice.h" |
||||
|
#include "cktdefs.h" |
||||
|
|
||||
|
#include "cm.h" |
||||
|
#include "mif.h" |
||||
|
#include "evt.h" |
||||
|
|
||||
|
#include "evtproto.h" |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
cm_event_alloc() |
||||
|
|
||||
|
This function is called from code model C functions to allocate |
||||
|
state storage for a particular event-driven |
||||
|
instance. It is similar to the |
||||
|
function cm_analog_alloc() used by analog models, but allocates states |
||||
|
that are rotated during event-driven 'timesteps' instead of analog |
||||
|
timesteps. |
||||
|
*/ |
||||
|
|
||||
|
|
||||
|
void *cm_event_alloc( |
||||
|
int tag, /* The user-specified tag for the memory block */ |
||||
|
int bytes) /* The number of bytes to be allocated */ |
||||
|
{ |
||||
|
|
||||
|
int inst_index; |
||||
|
int num_tags; |
||||
|
|
||||
|
MIFinstance *here; |
||||
|
CKTcircuit *ckt; |
||||
|
|
||||
|
void *ptr; |
||||
|
|
||||
|
Evt_State_Desc_t **desc_ptr; |
||||
|
Evt_State_Desc_t *desc; |
||||
|
|
||||
|
Evt_State_Data_t *state_data; |
||||
|
Evt_State_t *state; |
||||
|
|
||||
|
|
||||
|
/* Get the address of the ckt and instance structs from g_mif_info */ |
||||
|
here = g_mif_info.instance; |
||||
|
ckt = g_mif_info.ckt; |
||||
|
|
||||
|
|
||||
|
/* If not initialization pass, return error */ |
||||
|
if(here->initialized) { |
||||
|
g_mif_info.errmsg = |
||||
|
"ERROR - cm_event_alloc() - Cannot alloc when not initialization pass\n"; |
||||
|
return(NULL); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* Get pointers for fast access */ |
||||
|
inst_index = here->inst_index; |
||||
|
state_data = ckt->evt->data.state; |
||||
|
|
||||
|
|
||||
|
/* Scan state descriptor list to determine if tag is present and to */ |
||||
|
/* find the end of the list. Report error if duplicate tag */ |
||||
|
desc_ptr = &(state_data->desc[inst_index]); |
||||
|
desc = *desc_ptr; |
||||
|
num_tags = 1; |
||||
|
while(desc) { |
||||
|
if(desc->tag == tag) { |
||||
|
g_mif_info.errmsg = |
||||
|
"ERROR - cm_event_alloc() - Duplicate tag\n"; |
||||
|
return(NULL); |
||||
|
} |
||||
|
desc_ptr = &(desc->next); |
||||
|
desc = *desc_ptr; |
||||
|
num_tags++; |
||||
|
} |
||||
|
|
||||
|
/* Create a new state description structure at end of list */ |
||||
|
/* and fill in the data and update the total size */ |
||||
|
*desc_ptr = (void *) MALLOC(sizeof(Evt_State_Desc_t)); |
||||
|
desc = *desc_ptr; |
||||
|
desc->tag = tag; |
||||
|
desc->size = bytes; |
||||
|
desc->offset = state_data->total_size[inst_index]; |
||||
|
state_data->total_size[inst_index] += bytes; |
||||
|
|
||||
|
/* Create a new state structure if list starting at head is null */ |
||||
|
state = state_data->head[inst_index]; |
||||
|
if(state == NULL) { |
||||
|
state = (void *) MALLOC(sizeof(Evt_State_t)); |
||||
|
state_data->head[inst_index] = state; |
||||
|
} |
||||
|
|
||||
|
/* Create or enlarge the block and set the time */ |
||||
|
if(num_tags == 1) |
||||
|
state->block = MALLOC(state_data->total_size[inst_index]); |
||||
|
else |
||||
|
state->block = REALLOC(state->block, |
||||
|
state_data->total_size[inst_index]); |
||||
|
|
||||
|
state->step = g_mif_info.circuit.evt_step; |
||||
|
|
||||
|
|
||||
|
/* Return allocated memory */ |
||||
|
ptr = ((char *)state->block) + desc->offset; |
||||
|
return(ptr); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
/* |
||||
|
cm_event_get_ptr() |
||||
|
|
||||
|
This function is called from code model C functions to return a |
||||
|
pointer to state storage allocated with cm_event_alloc(). A tag |
||||
|
specified in its argument list is used to locate the state in |
||||
|
question. A second argument specifies whether the desired state |
||||
|
is for the current timestep or from a preceding timestep. The |
||||
|
location of the state in memory is then computed and returned. |
||||
|
*/ |
||||
|
|
||||
|
|
||||
|
void *cm_event_get_ptr( |
||||
|
int tag, /* The user-specified tag for the memory block */ |
||||
|
int timepoint) /* The timepoint - 0=current, 1=previous */ |
||||
|
{ |
||||
|
|
||||
|
int i; |
||||
|
int inst_index; |
||||
|
|
||||
|
MIFinstance *here; |
||||
|
CKTcircuit *ckt; |
||||
|
|
||||
|
void *ptr; |
||||
|
|
||||
|
Evt_State_Desc_t *desc; |
||||
|
|
||||
|
Evt_State_Data_t *state_data; |
||||
|
Evt_State_t *state; |
||||
|
|
||||
|
|
||||
|
/* Get the address of the ckt and instance structs from g_mif_info */ |
||||
|
here = g_mif_info.instance; |
||||
|
ckt = g_mif_info.ckt; |
||||
|
|
||||
|
|
||||
|
/* If initialization pass, return error */ |
||||
|
if((! here->initialized) && (timepoint > 0)) { |
||||
|
g_mif_info.errmsg = |
||||
|
"ERROR - cm_event_get_ptr() - Cannot get_ptr(tag,1) during initialization pass\n"; |
||||
|
return(NULL); |
||||
|
} |
||||
|
|
||||
|
/* Get pointers for fast access */ |
||||
|
inst_index = here->inst_index; |
||||
|
state_data = ckt->evt->data.state; |
||||
|
|
||||
|
/* Scan state descriptor list to find the descriptor for this tag. */ |
||||
|
/* Report error if tag not found */ |
||||
|
desc = state_data->desc[inst_index]; |
||||
|
while(desc) { |
||||
|
if(desc->tag == tag) |
||||
|
break; |
||||
|
desc = desc->next; |
||||
|
} |
||||
|
|
||||
|
if(desc == NULL) { |
||||
|
g_mif_info.errmsg = |
||||
|
"ERROR - cm_event_get_ptr() - Specified tag not found\n"; |
||||
|
return(NULL); |
||||
|
} |
||||
|
|
||||
|
/* Get the state pointer from the current array */ |
||||
|
state = *(state_data->tail[inst_index]); |
||||
|
|
||||
|
/* Backup the specified number of timesteps */ |
||||
|
for(i = 0; i < timepoint; i++) |
||||
|
if(state->prev) |
||||
|
state = state->prev; |
||||
|
|
||||
|
/* Return pointer */ |
||||
|
ptr = ((char *) state->block) + desc->offset; |
||||
|
return(ptr); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
/* |
||||
|
cm_event_queue() |
||||
|
|
||||
|
This function queues an event for an instance participating |
||||
|
in the event-driven algorithm. |
||||
|
*/ |
||||
|
|
||||
|
|
||||
|
int cm_event_queue( |
||||
|
double time) /* The time of the event to be queued */ |
||||
|
{ |
||||
|
|
||||
|
MIFinstance *here; |
||||
|
CKTcircuit *ckt; |
||||
|
|
||||
|
|
||||
|
/* Get the address of the ckt and instance structs from g_mif_info */ |
||||
|
here = g_mif_info.instance; |
||||
|
ckt = g_mif_info.ckt; |
||||
|
|
||||
|
/* If breakpoint time <= current event time, return error */ |
||||
|
if(time <= g_mif_info.circuit.evt_step) { |
||||
|
g_mif_info.errmsg = |
||||
|
"ERROR - cm_event_queue() - Event time cannot be <= current time\n"; |
||||
|
return(MIF_ERROR); |
||||
|
} |
||||
|
|
||||
|
/* Add the event time to the inst queue */ |
||||
|
EVTqueue_inst(ckt, here->inst_index, g_mif_info.circuit.evt_step, |
||||
|
time); |
||||
|
|
||||
|
return(MIF_OK); |
||||
|
} |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue