You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
369 lines
8.6 KiB
369 lines
8.6 KiB
/*============================================================================
|
|
FILE EVTprint.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 EVTprint which is used to provide a simple
|
|
tabular output of event-driven node data. This printout is invoked
|
|
through a new nutmeg command called 'eprint' which takes event-driven
|
|
node names as argument.
|
|
|
|
INTERFACES
|
|
|
|
void EVTprint(wordlist *wl)
|
|
|
|
REFERENCED FILES
|
|
|
|
None.
|
|
|
|
NON-STANDARD FEATURES
|
|
|
|
None.
|
|
|
|
============================================================================*/
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include "ngspice.h"
|
|
//#include "misc.h"
|
|
|
|
#include "cpstd.h"
|
|
|
|
#include "mif.h"
|
|
#include "evt.h"
|
|
#include "evtudn.h"
|
|
|
|
#include "evtproto.h"
|
|
|
|
|
|
|
|
static int get_index(char *node_name);
|
|
|
|
static void print_data(
|
|
Mif_Boolean_t dcop,
|
|
double step,
|
|
char **node_value,
|
|
int nargs);
|
|
|
|
/*
|
|
EVTprint
|
|
|
|
This function implements the 'eprint' command used to print
|
|
event-driven node values and messages from the latest simulation.
|
|
|
|
This is a simple prototype implementation of the
|
|
eprint command for testing purposes. It is currently lacking
|
|
in the following areas:
|
|
|
|
1) It accepts only up to 16 nodes.
|
|
|
|
2) It does not support the selected printing of different
|
|
members of a user-defined data struct.
|
|
|
|
3) It is dumb in its output formatting - just tries to print
|
|
everything on a line with 4 space separators.
|
|
|
|
4) It works only for the latest simulation - i.e. it does not
|
|
use the evt jobs structure to find old results.
|
|
|
|
5) It does not allow a range of timesteps to be selected.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define EPRINT_MAXARGS 16
|
|
|
|
|
|
void EVTprint(
|
|
wordlist *wl) /* The command line entered by user */
|
|
{
|
|
|
|
int i;
|
|
int nargs;
|
|
int num_ports;
|
|
|
|
wordlist *w;
|
|
|
|
char *node_name[EPRINT_MAXARGS];
|
|
int node_index[EPRINT_MAXARGS];
|
|
int udn_index[EPRINT_MAXARGS];
|
|
Evt_Node_t *node_data[EPRINT_MAXARGS];
|
|
char *node_value[EPRINT_MAXARGS];
|
|
|
|
CKTcircuit *ckt;
|
|
|
|
Evt_Node_Info_t **node_table;
|
|
Evt_Port_Info_t **port_table;
|
|
|
|
Mif_Boolean_t more;
|
|
Mif_Boolean_t dcop;
|
|
|
|
double step;
|
|
double next_step;
|
|
double this_step;
|
|
|
|
char *value;
|
|
|
|
Evt_Msg_t *msg_data;
|
|
Evt_Statistic_t *statistics;
|
|
|
|
|
|
/* Count the number of arguments to the command */
|
|
nargs = 0;
|
|
w = wl;
|
|
while(w) {
|
|
nargs++;
|
|
w = w->wl_next;
|
|
}
|
|
|
|
if(nargs < 1) {
|
|
printf("Usage: eprint <node1> <node2> ...\n");
|
|
return;
|
|
}
|
|
if(nargs > EPRINT_MAXARGS) {
|
|
printf("ERROR - eprint currently limited to 16 arguments\n");
|
|
return;
|
|
}
|
|
|
|
/* Get needed pointers */
|
|
ckt = g_mif_info.ckt;
|
|
node_table = ckt->evt->info.node_table;
|
|
|
|
/* Get data for each argument */
|
|
w = wl;
|
|
for(i = 0; i < nargs; i++) {
|
|
node_name[i] = w->wl_word;
|
|
node_index[i] = get_index(node_name[i]);
|
|
if(node_index[i] < 0) {
|
|
printf("ERROR - Node %s is not an event node.\n", node_name[i]);
|
|
return;
|
|
}
|
|
udn_index[i] = node_table[node_index[i]]->udn_index;
|
|
node_data[i] = ckt->evt->data.node->head[node_index[i]];
|
|
node_value[i] = "";
|
|
w = w->wl_next;
|
|
}
|
|
|
|
|
|
/* Print results data */
|
|
printf("\n**** Results Data ****\n\n");
|
|
|
|
/* Print the column identifiers */
|
|
printf("Time or Step\n");
|
|
for(i = 0; i < nargs; i++)
|
|
printf("%s\n",node_name[i]);
|
|
printf("\n\n");
|
|
|
|
/* Scan the node data and determine if the first vector */
|
|
/* is for a DCOP analysis or the first step in a swept DC */
|
|
/* or transient analysis. Also, determine if there is */
|
|
/* more data following it and if so, what the next step */
|
|
/* is. */
|
|
more = MIF_FALSE;
|
|
dcop = MIF_FALSE;
|
|
next_step = 1e30;
|
|
for(i = 0; i < nargs; i++) {
|
|
if(node_data[i]->op)
|
|
dcop = MIF_TRUE;
|
|
else
|
|
step = node_data[i]->step;
|
|
(*(g_evt_udn_info[udn_index[i]]->print_val))
|
|
(node_data[i]->node_value, "all", &value);
|
|
node_value[i] = value;
|
|
node_data[i] = node_data[i]->next;
|
|
if(node_data[i]) {
|
|
more = MIF_TRUE;
|
|
if(node_data[i]->step < next_step)
|
|
next_step = node_data[i]->step;
|
|
}
|
|
}
|
|
|
|
/* Print the data */
|
|
print_data(dcop, step, node_value, nargs);
|
|
|
|
/* While there is more data, get the next values and print */
|
|
while(more) {
|
|
|
|
more = MIF_FALSE;
|
|
this_step = next_step;
|
|
next_step = 1e30;
|
|
|
|
for(i = 0; i < nargs; i++) {
|
|
|
|
if(node_data[i]) {
|
|
if(node_data[i]->step == this_step) {
|
|
(*(g_evt_udn_info[udn_index[i]]->print_val))
|
|
(node_data[i]->node_value, "all", &value);
|
|
node_value[i] = value;
|
|
node_data[i] = node_data[i]->next;
|
|
}
|
|
if(node_data[i]) {
|
|
more = MIF_TRUE;
|
|
if(node_data[i]->step < next_step)
|
|
next_step = node_data[i]->step;
|
|
}
|
|
|
|
} /* end if node_data not NULL */
|
|
|
|
} /* end for number of args */
|
|
|
|
print_data(MIF_FALSE, this_step, node_value, nargs);
|
|
|
|
} /* end while there is more data */
|
|
printf("\n\n");
|
|
|
|
|
|
/* Print messages for all ports */
|
|
printf("\n**** Messages ****\n\n");
|
|
|
|
num_ports = ckt->evt->counts.num_ports;
|
|
port_table = ckt->evt->info.port_table;
|
|
|
|
for(i = 0; i < num_ports; i++) {
|
|
|
|
/* Get pointer to messages for this port */
|
|
msg_data = ckt->evt->data.msg->head[i];
|
|
|
|
/* If no messages on this port, skip */
|
|
if(! msg_data)
|
|
continue;
|
|
|
|
/* Print the port description */
|
|
printf("Node: %s Inst: %s Conn: %s Port: %d\n\n",
|
|
port_table[i]->node_name,
|
|
port_table[i]->inst_name,
|
|
port_table[i]->conn_name,
|
|
port_table[i]->port_num);
|
|
|
|
/* Print the messages on this port */
|
|
while(msg_data) {
|
|
if(msg_data->op)
|
|
printf("DCOP ");
|
|
else
|
|
printf("%-16.9e", msg_data->step);
|
|
printf("%s\n", msg_data->text);
|
|
msg_data = msg_data->next;
|
|
}
|
|
printf("\n\n");
|
|
|
|
} /* end for number of ports */
|
|
|
|
|
|
/* Print statistics */
|
|
printf("\n**** Statistics ****\n\n");
|
|
|
|
statistics = ckt->evt->data.statistics;
|
|
printf("Operating point analog/event alternations: %d\n",
|
|
statistics->op_alternations);
|
|
printf("Operating point load calls: %d\n",
|
|
statistics->op_load_calls);
|
|
printf("Operating point event passes: %d\n",
|
|
statistics->op_event_passes);
|
|
printf("Transient analysis load calls: %d\n",
|
|
statistics->tran_load_calls);
|
|
printf("Transient analysis timestep backups: %d\n",
|
|
statistics->tran_time_backups);
|
|
|
|
printf("\n\n");
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
get_index
|
|
|
|
This function determines the index of a specified event-driven node.
|
|
*/
|
|
|
|
|
|
static int get_index(
|
|
char *node_name /* The name of the node to search for */
|
|
)
|
|
{
|
|
|
|
/* Get the event-driven node index for the specified name */
|
|
|
|
int index;
|
|
|
|
Mif_Boolean_t found;
|
|
Evt_Node_Info_t *node;
|
|
CKTcircuit *ckt;
|
|
|
|
|
|
/* Scan list of nodes in event structure to see if there */
|
|
|
|
found = MIF_FALSE;
|
|
index = 0;
|
|
|
|
ckt = g_mif_info.ckt;
|
|
node = ckt->evt->info.node_list;
|
|
|
|
while(node) {
|
|
if(strcmp(node_name, node->name) == 0) {
|
|
found = MIF_TRUE;
|
|
break;
|
|
}
|
|
else {
|
|
index++;
|
|
node = node->next;
|
|
}
|
|
}
|
|
|
|
/* Return the index or -1 if not found */
|
|
if(! found)
|
|
return(-1);
|
|
else
|
|
return(index);
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
print_data
|
|
|
|
This function prints the values of one or more nodes to
|
|
standard output.
|
|
*/
|
|
|
|
|
|
static void print_data(
|
|
Mif_Boolean_t dcop, /* Is this the operating point data */
|
|
double step, /* The analysis step if dcop */
|
|
char **node_value, /* The array of values to be printed */
|
|
int nargs) /* The size of the value array */
|
|
{
|
|
|
|
int i;
|
|
char step_str[100];
|
|
|
|
if(dcop)
|
|
strcpy(step_str, "DCOP ");
|
|
else
|
|
sprintf(step_str, "%-16.9e", step);
|
|
|
|
printf("%s", step_str);
|
|
for(i = 0; i < nargs; i++)
|
|
printf(" %s", node_value[i]);
|
|
printf("\n");
|
|
}
|