ngspice/src/xspice/evt/evttermi.c

516 lines
14 KiB
C

/*============================================================================
FILE EVTtermInsert.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 function EVTtermInsert which is called by
MIF_INP2A during the parsing of the input deck. EVTtermInsert is
similar to SPICE3's INPtermInsert except that it is used when the node
type is event-driven. Calls to this function build the info lists
for instances, nodes, outputs, and ports. The completion of the info
struct is carried out by EVTinit following the parsing of all
instances in the deck.
INTERFACES
void EVTtermInsert(
CKTcircuit *ckt,
MIFinstance *fast,
char *node_name,
char *type_name,
int conn_num,
int port_num,
char **err_msg)
REFERENCED FILES
None.
NON-STANDARD FEATURES
None.
============================================================================*/
#include "ngspice/ngspice.h"
//#include "misc.h"
#include "ngspice/cktdefs.h"
//#include "util.h"
#include "ngspice/mif.h"
#include "ngspice/evt.h"
#include "ngspice/evtudn.h"
#include "ngspice/mifproto.h"
#include "ngspice/evtproto.h"
static void EVTinst_insert(
CKTcircuit *ckt,
MIFinstance *fast,
int *inst_index,
char **err_msg);
static void EVTnode_insert(
CKTcircuit *ckt,
MIFinstance *fast,
int inst_index,
char *node_name,
char *type_name,
int conn_num,
int port_num,
int *node_index,
int *output_subindex,
char **err_msg);
static void EVTport_insert(
CKTcircuit *ckt,
MIFinstance *fast,
int inst_index,
int node_index,
char *node_name,
int conn_num,
int port_num,
int *port_index,
char **err_msg);
static void EVToutput_insert(
CKTcircuit *ckt,
MIFinstance *fast,
int inst_index,
int node_index,
int port_index,
int output_subindex,
int conn_num,
int port_num,
char **err_msg);
/*
EVTtermInsert
This function is called by MIF_INP2A during the parsing of the input
deck. EVTtermInsert is similar to 3C1's INPtermInsert except that it is
used when the node type is event-driven. Calls to this function build
the info lists for instances, nodes, outputs, and ports. The
completion of the info struct is carried out by EVTinit following
the parsing of all instances in the deck.
*/
void EVTtermInsert(
CKTcircuit *ckt, /* The circuit structure */
MIFinstance *fast, /* The instance being parsed */
char *node_name, /* The node name */
char *type_name, /* The type of node */
int conn_num, /* The port connection number */
int port_num, /* The sub-port number - 0 for scalar ports */
char **err_msg) /* Returned error message if any */
{
int inst_index;
int node_index;
int port_index;
int output_subindex;
/* Get the instance index and create new entry in inst */
/* info list if this is a new instance. */
EVTinst_insert(ckt, fast, &inst_index, err_msg);
if(*err_msg)
return;
/* Get the node index and create new entry in node info */
/* list if this is a new node */
EVTnode_insert(ckt, fast, inst_index, node_name, type_name,
conn_num, port_num, &node_index, &output_subindex,
err_msg);
if(*err_msg)
return;
/* Create new entry in port info list and return port index */
EVTport_insert(ckt, fast, inst_index, node_index, node_name, conn_num,
port_num, &port_index, err_msg);
if(*err_msg)
return;
/* Create new entry in output info list if appropriate */
if(fast->conn[conn_num]->is_output) {
EVToutput_insert(ckt, fast, inst_index, node_index, port_index,
output_subindex, conn_num, port_num, err_msg);
if(*err_msg)
return;
}
}
/*
EVTinst_insert
This function locates or creates a new entry for the specified
instance in the event-driven ``info'' structures during parsing.
*/
static void EVTinst_insert(
CKTcircuit *ckt, /* The circuit structure */
MIFinstance *fast, /* The instance being parsed */
int *inst_index, /* The index found or added */
char **err_msg) /* Error message if any */
{
Mif_Boolean_t found;
int index;
Evt_Inst_Info_t *inst;
Evt_Inst_Info_t **inst_ptr;
NG_IGNORE(err_msg);
/* Scan list of instances in event structure to see if already there */
/* and get the index */
found = MIF_FALSE;
index = 0;
inst = ckt->evt->info.inst_list;
inst_ptr = &(ckt->evt->info.inst_list);
while(inst) {
if(inst->inst_ptr == fast) {
found = MIF_TRUE;
break;
}
else {
index++;
inst_ptr = &(inst->next);
inst = inst->next;
}
}
/* If not found, create a new entry in list and increment the */
/* instance count in the event structure */
if(! found) {
*inst_ptr = TMALLOC(Evt_Inst_Info_t, 1);
inst = *inst_ptr;
inst->next = NULL;
inst->inst_ptr = fast;
index = ckt->evt->counts.num_insts;
(ckt->evt->counts.num_insts)++;
}
/* Record the inst index in the MIFinstance structure and return it */
fast->inst_index = index;
*inst_index = index;
}
/*
EVTnode_insert
This function locates or creates a new entry for the specified
node in the event-driven ``info'' structures during parsing.
*/
static void EVTnode_insert(
CKTcircuit *ckt, /* The circuit structure */
MIFinstance *fast, /* The instance being parsed */
int inst_index, /* The index of inst in evt structures */
char *node_name, /* The node name */
char *type_name, /* The node type specified */
int conn_num, /* The port connection number */
int port_num, /* The sub-port number - 0 if scalar port */
int *node_index, /* The node index found or added */
int *output_subindex, /* The output number on this node */
char **err_msg) /* Error message text if any */
{
int i;
int udn_index=0;
Mif_Boolean_t found;
int index;
Evt_Node_Info_t *node;
Evt_Node_Info_t **node_ptr;
Evt_Inst_Index_t *inst;
Evt_Inst_Index_t **inst_ptr;
/* *************************************** */
/* Get and check the node type information */
/* *************************************** */
/* Scan the list of user-defined node types and get the index */
found = MIF_FALSE;
for(i = 0; i < g_evt_num_udn_types; i++) {
if(strcmp(type_name, g_evt_udn_info[i]->name) == 0) {
udn_index = i;
found = MIF_TRUE;
break;
}
}
/* Report error if not recognized */
if(! found) {
*err_msg = "Unrecognized connection type";
return;
}
/* If inverted, check to be sure invert function exists for type */
if(fast->conn[conn_num]->port[port_num]->invert) {
if(g_evt_udn_info[udn_index]->invert == NULL) {
*err_msg = "Connection type cannot be inverted";
return;
}
}
/* ******************************************* */
/* Find/create entry in event-driven node list */
/* ******************************************* */
/* Scan list of nodes in event structure to see if already there */
/* and get the index */
found = MIF_FALSE;
index = 0;
node = ckt->evt->info.node_list;
node_ptr = &(ckt->evt->info.node_list);
while(node) {
if(strcmp(node_name, node->name) == 0) {
found = MIF_TRUE;
break;
}
else {
index++;
node_ptr = &(node->next);
node = node->next;
}
}
/* If found, verify that connection type is same as type of node */
if(found) {
if(udn_index != node->udn_index) {
*err_msg = "Node cannot have two different types";
return;
}
}
/* If not found, create a new entry in list and increment the */
/* node count in the event structure */
if(! found) {
*node_ptr = TMALLOC(Evt_Node_Info_t, 1);
node = *node_ptr;
node->next = NULL;
node->name = MIFcopy(node_name);
node->udn_index = udn_index;
index = ckt->evt->counts.num_nodes;
(ckt->evt->counts.num_nodes)++;
}
/* ******************************************* */
/* Update remaining items in node list struct */
/* ******************************************* */
/* Update flag on node that indicates if inversion is used by any */
/* instance inputs */
if(fast->conn[conn_num]->is_input)
if(! node->invert)
node->invert = fast->conn[conn_num]->port[port_num]->invert;
/* Increment counts of ports, outputs connected to node */
(node->num_ports)++;
if(fast->conn[conn_num]->is_output)
(node->num_outputs)++;
/* If this is an input, add instance to list if not already there */
if(fast->conn[conn_num]->is_input) {
found = MIF_FALSE;
inst = node->inst_list;
inst_ptr = &(node->inst_list);
while(inst) {
if(inst_index == inst->index) {
found = MIF_TRUE;
break;
}
else {
inst_ptr = &(inst->next);
inst = inst->next;
}
}
if(! found) {
(node->num_insts)++;
*inst_ptr = TMALLOC(Evt_Inst_Index_t, 1);
inst = *inst_ptr;
inst->next = NULL;
inst->index = inst_index;
}
}
/* Record the node index in the MIFinstance structure */
fast->conn[conn_num]->port[port_num]->evt_data.node_index = index;
/* Return the node index */
*node_index = index;
if(fast->conn[conn_num]->is_output)
*output_subindex = node->num_outputs - 1;
else
*output_subindex = 0; /* just for safety - shouldn't need this */
}
/*
EVTport_insert
This function locates or creates a new entry for the specified
port in the event-driven ``info'' structures during parsing.
*/
static void EVTport_insert(
CKTcircuit *ckt, /* The circuit structure */
MIFinstance *fast, /* The instance being parsed */
int inst_index, /* The index of inst in evt structures */
int node_index, /* The index of the node in evt structures */
char *node_name, /* The node name */
int conn_num, /* The port connection number */
int port_num, /* The sub-port number - 0 if scalar port */
int *port_index, /* The port index found or added */
char **err_msg) /* Error message text if any */
{
Evt_Port_Info_t *port;
Evt_Port_Info_t **port_ptr;
int index;
NG_IGNORE(err_msg);
/* Find the end of the port info list */
port = ckt->evt->info.port_list;
port_ptr = &(ckt->evt->info.port_list);
index = 0;
while(port) {
port_ptr = &(port->next);
port = port->next;
index++;
}
/* Update the port count and create a new entry in the list */
(ckt->evt->counts.num_ports)++;
*port_ptr = TMALLOC(Evt_Port_Info_t, 1);
port = *port_ptr;
/* Fill in the elements */
port->next = NULL;
port->inst_index = inst_index;
port->node_index = node_index;
port->node_name = MIFcopy(node_name);
port->inst_name = MIFcopy(fast->MIFname);
port->conn_name = MIFcopy(fast->conn[conn_num]->name);
port->port_num = port_num;
/* Record the port index in the MIFinstance structure */
fast->conn[conn_num]->port[port_num]->evt_data.port_index = index;
/* Return the port index */
*port_index = index;
}
/*
EVToutput_insert
This function locates or creates a new entry for the specified
output in the event-driven ``info'' structures during parsing.
*/
static void EVToutput_insert(
CKTcircuit *ckt, /* The circuit structure */
MIFinstance *fast, /* The instance being parsed */
int inst_index, /* The index of inst in evt structures */
int node_index, /* The index of the node in evt structures */
int port_index, /* The index of the port in the evt structures */
int output_subindex, /* The output on this node */
int conn_num, /* The port connection number */
int port_num, /* The sub-port number - 0 if scalar port */
char **err_msg) /* Error message text if any */
{
Evt_Output_Info_t *output;
Evt_Output_Info_t **output_ptr;
int index;
NG_IGNORE(err_msg);
/* Find the end of the port info list */
output = ckt->evt->info.output_list;
output_ptr = &(ckt->evt->info.output_list);
index = 0;
while(output) {
output_ptr = &(output->next);
output = output->next;
index++;
}
/* Update the port count and create a new entry in the list */
(ckt->evt->counts.num_outputs)++;
*output_ptr = TMALLOC(Evt_Output_Info_t, 1);
output = *output_ptr;
/* Fill in the elements */
output->next = NULL;
output->inst_index = inst_index;
output->node_index = node_index;
output->port_index = port_index;
output->output_subindex = output_subindex;
/* Record the output index and subindex in the MIFinstance structure */
fast->conn[conn_num]->port[port_num]->evt_data.output_index = index;
fast->conn[conn_num]->port[port_num]->evt_data.output_subindex
= output_subindex;
}