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.
1087 lines
32 KiB
1087 lines
32 KiB
/*============================================================================
|
|
FILE pp_lst.c
|
|
|
|
MEMBER OF process cmpp
|
|
|
|
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 used in processing the files:
|
|
|
|
modpath.lst
|
|
udnpath.lst
|
|
|
|
The files 'modpath.lst' and 'udnpath.lst' are read to get
|
|
the pathnames to directories containing the models and node types
|
|
desired in the simulator to be built. Files in each of these
|
|
directories are then examined to get the names of functions and/or
|
|
data structures that the simulator must know about. The names
|
|
are then checked for uniqueness, and finally, a collection of
|
|
files needed in the 'make' for the simulator are written.
|
|
|
|
INTERFACES
|
|
|
|
preprocess_lst_files()
|
|
|
|
REFERENCED FILES
|
|
|
|
None.
|
|
|
|
NON-STANDARD FEATURES
|
|
|
|
None.
|
|
|
|
============================================================================*/
|
|
|
|
#include "cmpp.h"
|
|
#include <ctype.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
|
|
extern int str_to_lower(char *s);
|
|
|
|
/*
|
|
void *malloc(unsigned size);
|
|
void *realloc(void *ptr, unsigned size);
|
|
*/
|
|
|
|
/* *********************************************************************** */
|
|
|
|
/*
|
|
* Information for processing the pathname files
|
|
*/
|
|
|
|
typedef struct {
|
|
char *path_name; /* Pathname read from model path file */
|
|
char *spice_name; /* Name of model from ifspec.ifs */
|
|
char *cfunc_name; /* Name of C fcn from ifspec.ifs */
|
|
Boolean_t spice_unique; /* True if spice name unique */
|
|
Boolean_t cfunc_unique; /* True if C fcn name unique */
|
|
} Model_Info_t;
|
|
|
|
|
|
typedef struct {
|
|
char *path_name; /* Pathname read from udn path file */
|
|
char *node_name; /* Name of node type */
|
|
Boolean_t unique; /* True if node type name unique */
|
|
} Node_Info_t;
|
|
|
|
|
|
|
|
/* *********************************************************************** */
|
|
|
|
|
|
static Status_t read_modpath(int *num_models, Model_Info_t **model_info);
|
|
static Status_t read_udnpath(int *num_nodes, Node_Info_t **node_info);
|
|
static Status_t read_model_names(int num_models, Model_Info_t *model_info);
|
|
static Status_t read_node_names(int num_nodes, Node_Info_t *node_info);
|
|
static Status_t check_uniqueness(int num_models, Model_Info_t *model_info,
|
|
int num_nodes, Node_Info_t *node_info);
|
|
static Status_t write_CMextrn(int num_models, Model_Info_t *model_info);
|
|
static Status_t write_CMinfo(int num_models, Model_Info_t *model_info);
|
|
static Status_t write_UDNextrn(int num_nodes, Node_Info_t *node_info);
|
|
static Status_t write_UDNinfo(int num_nodes, Node_Info_t *node_info);
|
|
static Status_t write_objects_inc(int num_models, Model_Info_t *model_info,
|
|
int num_nodes, Node_Info_t *node_info);
|
|
static Status_t read_udn_type_name(char *path, char **node_name);
|
|
|
|
|
|
/* *********************************************************************** */
|
|
|
|
|
|
/*
|
|
preprocess_lst_files
|
|
|
|
Function preprocess_lst_files is the top-level driver function for
|
|
preprocessing a simulator model path list file (modpath.lst).
|
|
This function calls read_ifs_file() requesting it to read and
|
|
parse the Interface Specification file (ifspec.ifs) to extract
|
|
the model name and associated C function name and place this
|
|
information into an internal data structure. It then calls
|
|
check_uniqueness() to verify that the model names and function
|
|
names are unique with respect to each other and to the models and
|
|
functions internal to SPICE 3C1. Following this check, it calls
|
|
write_CMextrn(), write_CMinfo(), and write_make_include() to
|
|
write out the C include files CMextrn.h and CMinfo.h required by
|
|
SPICE function SPIinit.c to define the models known to the
|
|
simulator, and to write out a make include file used by the make
|
|
utility to locate the object modules necessary to link the models
|
|
into the simulator.
|
|
*/
|
|
|
|
void preprocess_lst_files(void)
|
|
{
|
|
Status_t status; /* Return status */
|
|
Model_Info_t *model_info; /* Info about each model */
|
|
Node_Info_t *node_info; /* Info about each user-defined node type */
|
|
int num_models; /* The number of models */
|
|
int num_nodes; /* The number of user-defined nodes */
|
|
|
|
|
|
/* Get list of models from model pathname file */
|
|
status = read_modpath(&num_models, &model_info);
|
|
if(status != OK) {
|
|
exit(1);
|
|
}
|
|
|
|
/* Get list of node types from udn pathname file */
|
|
status = read_udnpath(&num_nodes, &node_info);
|
|
if(status != OK) {
|
|
exit(1);
|
|
}
|
|
|
|
|
|
/* Get the spice and C function names from the ifspec.ifs files */
|
|
status = read_model_names(num_models, model_info);
|
|
if(status != OK) {
|
|
exit(1);
|
|
}
|
|
|
|
/* Get the user-defined node type names */
|
|
status = read_node_names(num_nodes, node_info);
|
|
if(status != OK) {
|
|
exit(1);
|
|
}
|
|
|
|
|
|
/* Check to be sure the names are unique */
|
|
status = check_uniqueness(num_models, model_info,
|
|
num_nodes, node_info);
|
|
if(status != OK) {
|
|
exit(1);
|
|
}
|
|
|
|
|
|
/* Write out the CMextrn.h file used to compile SPIinit.c */
|
|
status = write_CMextrn(num_models, model_info);
|
|
if(status != OK) {
|
|
exit(1);
|
|
}
|
|
|
|
/* Write out the CMinfo.h file used to compile SPIinit.c */
|
|
status = write_CMinfo(num_models, model_info);
|
|
if(status != OK) {
|
|
exit(1);
|
|
}
|
|
|
|
|
|
/* Write out the UDNextrn.h file used to compile SPIinit.c */
|
|
status = write_UDNextrn(num_nodes, node_info);
|
|
if(status != OK) {
|
|
exit(1);
|
|
}
|
|
|
|
/* Write out the UDNinfo.h file used to compile SPIinit.c */
|
|
status = write_UDNinfo(num_nodes, node_info);
|
|
if(status != OK) {
|
|
exit(1);
|
|
}
|
|
|
|
|
|
/* Write the make_include file used to link the models and */
|
|
/* user-defined node functions with the simulator */
|
|
status = write_objects_inc(num_models, model_info,
|
|
num_nodes, node_info);
|
|
if(status != OK) {
|
|
exit(1);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* *********************************************************************** */
|
|
|
|
|
|
/*
|
|
read_modpath
|
|
|
|
This function opens the modpath.lst file, reads the pathnames from the
|
|
file, and puts them into an internal data structure for future
|
|
processing.
|
|
*/
|
|
|
|
|
|
static Status_t read_modpath(
|
|
int *num_models, /* Number of model pathnames found */
|
|
Model_Info_t **model_info /* Info about each model */
|
|
)
|
|
{
|
|
FILE *fp; /* Model pathname file pointer */
|
|
char msg[MAX_PATH_LEN+257]; /* space for an error message */
|
|
char path[MAX_PATH_LEN+2]; /* space to read pathnames into */
|
|
Model_Info_t *model = NULL; /* temporary pointer to model info */
|
|
|
|
int n;
|
|
int i;
|
|
int j;
|
|
int len;
|
|
int line_num;
|
|
|
|
static char *filename = MODPATH_FILENAME;
|
|
|
|
|
|
/* Initialize number of models to zero in case of error */
|
|
*num_models = 0;
|
|
|
|
/* Open the model pathname file */
|
|
fp = fopen(filename, "r");
|
|
|
|
if(fp == NULL) {
|
|
sprintf(msg, "ERROR - File not found: %s", filename);
|
|
print_error(msg);
|
|
return(ERROR);
|
|
}
|
|
|
|
/* Read the pathnames from the file, one line at a time until EOF */
|
|
n = 0;
|
|
line_num = 0;
|
|
while( fgets(path, sizeof(path), fp) ) {
|
|
|
|
line_num++;
|
|
len = strlen(path);
|
|
|
|
/* If line was too long for buffer, exit with error */
|
|
if(len > MAX_PATH_LEN) {
|
|
sprintf(msg, "ERROR - Line %d of %s exceeds %d characters",
|
|
line_num, filename, MAX_PATH_LEN);
|
|
print_error(msg);
|
|
return(ERROR);
|
|
}
|
|
|
|
/* Strip white space including newline */
|
|
for(i = 0, j = 0; i < len; ) {
|
|
if(isspace(path[i])) {
|
|
i++;
|
|
}
|
|
else {
|
|
path[j] = path[i];
|
|
i++;
|
|
j++;
|
|
}
|
|
}
|
|
path[j] = '\0';
|
|
len = j;
|
|
|
|
/* Strip trailing '/' if any */
|
|
if(path[len - 1] == '/')
|
|
path[--len] = '\0';
|
|
|
|
/* If blank line, continue */
|
|
if(len == 0)
|
|
continue;
|
|
|
|
/* Make sure pathname is short enough to add a filename at the end */
|
|
if(len > (MAX_PATH_LEN - (MAX_FN_LEN + 1)) ) {
|
|
sprintf(msg, "ERROR - Pathname on line %d of %s exceeds %d characters",
|
|
line_num, filename, (MAX_PATH_LEN - (MAX_FN_LEN + 1)));
|
|
print_error(msg);
|
|
return(ERROR);
|
|
}
|
|
|
|
/* Allocate and initialize a new model info structure */
|
|
if(n == 0)
|
|
model = (Model_Info_t *) malloc(sizeof(Model_Info_t));
|
|
else
|
|
model = (Model_Info_t *) realloc(model, (n + 1) * sizeof(Model_Info_t));
|
|
model[n].path_name = NULL;
|
|
model[n].spice_name = NULL;
|
|
model[n].cfunc_name = NULL;
|
|
model[n].spice_unique = TRUE;
|
|
model[n].cfunc_unique = TRUE;
|
|
|
|
/* Put pathname into info structure */
|
|
model[n].path_name = (char *) malloc(len+1);
|
|
strcpy(model[n].path_name, path);
|
|
|
|
/* Increment count of paths read */
|
|
n++;
|
|
}
|
|
|
|
|
|
/* Close model pathname file and return data read */
|
|
fclose(fp);
|
|
|
|
*num_models = n;
|
|
*model_info = model;
|
|
|
|
return(OK);
|
|
|
|
}
|
|
|
|
|
|
/* *********************************************************************** */
|
|
|
|
|
|
/*
|
|
read_udnpath
|
|
|
|
This function opens the udnpath.lst file, reads the pathnames from the
|
|
file, and puts them into an internal data structure for future
|
|
processing.
|
|
*/
|
|
|
|
|
|
static Status_t read_udnpath(
|
|
int *num_nodes, /* Number of node pathnames found */
|
|
Node_Info_t **node_info /* Info about each node */
|
|
)
|
|
{
|
|
FILE *fp; /* Udn pathname file pointer */
|
|
char msg[MAX_PATH_LEN+257]; /* space for an error message */
|
|
char path[MAX_PATH_LEN+2]; /* space to read pathnames into */
|
|
Node_Info_t *node = NULL; /* temporary pointer to node info */
|
|
|
|
int n;
|
|
int i;
|
|
int j;
|
|
int len;
|
|
int line_num;
|
|
|
|
static char *filename = UDNPATH_FILENAME;
|
|
|
|
|
|
/* Initialize number of nodes to zero in case of error */
|
|
*num_nodes = 0;
|
|
|
|
/* Open the node pathname file */
|
|
fp = fopen(filename, "r");
|
|
|
|
/* For backward compatibility, return with WARNING only if file not found */
|
|
if(fp == NULL) {
|
|
sprintf(msg, "WARNING - File not found: %s", filename);
|
|
print_error(msg);
|
|
return(OK);
|
|
}
|
|
|
|
/* Read the pathnames from the file, one line at a time until EOF */
|
|
n = 0;
|
|
line_num = 0;
|
|
while( fgets(path, sizeof(path), fp) ) {
|
|
|
|
line_num++;
|
|
len = strlen(path);
|
|
|
|
/* If line was too long for buffer, exit with error */
|
|
if(len > MAX_PATH_LEN) {
|
|
sprintf(msg, "ERROR - Line %d of %s exceeds %d characters",
|
|
line_num, filename, MAX_PATH_LEN);
|
|
print_error(msg);
|
|
return(ERROR);
|
|
}
|
|
|
|
/* Strip white space including newline */
|
|
for(i = 0, j = 0; i < len; ) {
|
|
if(isspace(path[i])) {
|
|
i++;
|
|
}
|
|
else {
|
|
path[j] = path[i];
|
|
i++;
|
|
j++;
|
|
}
|
|
}
|
|
path[j] = '\0';
|
|
len = j;
|
|
|
|
/* Strip trailing '/' if any */
|
|
if(path[len - 1] == '/')
|
|
path[--len] = '\0';
|
|
|
|
/* If blank line, continue */
|
|
if(len == 0)
|
|
continue;
|
|
|
|
/* Make sure pathname is short enough to add a filename at the end */
|
|
if(len > (MAX_PATH_LEN - (MAX_FN_LEN + 1)) ) {
|
|
sprintf(msg, "ERROR - Pathname on line %d of %s exceeds %d characters",
|
|
line_num, filename, (MAX_PATH_LEN - (MAX_FN_LEN + 1)));
|
|
print_error(msg);
|
|
return(ERROR);
|
|
}
|
|
|
|
/* Allocate and initialize a new node info structure */
|
|
if(n == 0)
|
|
node = (Node_Info_t *) malloc(sizeof(Node_Info_t));
|
|
else
|
|
node = (Node_Info_t *) realloc(node, (n + 1) * sizeof(Node_Info_t));
|
|
node[n].path_name = NULL;
|
|
node[n].node_name = NULL;
|
|
node[n].unique = TRUE;
|
|
|
|
/* Put pathname into info structure */
|
|
node[n].path_name = (char *) malloc(len+1);
|
|
strcpy(node[n].path_name, path);
|
|
|
|
/* Increment count of paths read */
|
|
n++;
|
|
}
|
|
|
|
|
|
/* Close node pathname file and return data read */
|
|
fclose(fp);
|
|
|
|
*num_nodes = n;
|
|
*node_info = node;
|
|
|
|
return(OK);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* *********************************************************************** */
|
|
|
|
|
|
/*
|
|
read_model_names
|
|
|
|
This function opens each of the models and gets the names of the model
|
|
and the C function into the internal model information structure.
|
|
*/
|
|
|
|
static Status_t read_model_names(
|
|
int num_models, /* Number of model pathnames */
|
|
Model_Info_t *model_info /* Info about each model */
|
|
)
|
|
{
|
|
Boolean_t all_found; /* True if all ifspec files read */
|
|
int i; /* A temporary counter */
|
|
char msg[MAX_PATH_LEN+257]; /* space for an error message */
|
|
char path[MAX_PATH_LEN+1]; /* full pathname to ifspec file */
|
|
Status_t status; /* Return status */
|
|
Ifs_Table_t ifs_table; /* Repository for info read from ifspec file */
|
|
|
|
|
|
/* For each model found in model pathname file, read the interface */
|
|
/* spec file to get the SPICE and C function names into model_info */
|
|
|
|
for(i = 0, all_found = TRUE; i < num_models; i++) {
|
|
|
|
/* Form the full pathname to the interface spec file */
|
|
strcpy(path, model_info[i].path_name);
|
|
strcat(path, "/");
|
|
strcat(path, IFSPEC_FILENAME);
|
|
|
|
/* Read the SPICE and C function names from the interface spec file */
|
|
status = read_ifs_file(path, GET_IFS_NAME, &ifs_table);
|
|
|
|
/* Transfer the names into the model_info structure */
|
|
if(status == OK) {
|
|
model_info[i].spice_name = ifs_table.name.model_name;
|
|
model_info[i].cfunc_name = ifs_table.name.c_fcn_name;
|
|
}
|
|
else {
|
|
all_found = FALSE;
|
|
sprintf(msg, "ERROR - Problems reading %s in directory %s",
|
|
IFSPEC_FILENAME, model_info[i].path_name);
|
|
print_error(msg);
|
|
}
|
|
}
|
|
|
|
if(all_found)
|
|
return(OK);
|
|
else
|
|
return(ERROR);
|
|
|
|
}
|
|
|
|
|
|
/* *********************************************************************** */
|
|
|
|
|
|
/*
|
|
read_node_names
|
|
|
|
This function opens each of the user-defined node definition files
|
|
and gets the names of the node into the internal information structure.
|
|
*/
|
|
|
|
|
|
static Status_t read_node_names(
|
|
int num_nodes, /* Number of node pathnames */
|
|
Node_Info_t *node_info /* Info about each node */
|
|
)
|
|
{
|
|
Boolean_t all_found; /* True if all files read OK */
|
|
int i; /* A temporary counter */
|
|
char msg[MAX_PATH_LEN+257]; /* space for an error message */
|
|
char path[MAX_PATH_LEN+1]; /* full pathname to file */
|
|
Status_t status; /* Return status */
|
|
char *node_name; /* Name of node type read from file */
|
|
|
|
/* For each node found in node pathname file, read the udnfunc.c */
|
|
/* file to get the node type names into node_info */
|
|
|
|
for(i = 0, all_found = TRUE; i < num_nodes; i++) {
|
|
|
|
/* Form the full pathname to the interface spec file */
|
|
strcpy(path, node_info[i].path_name);
|
|
strcat(path, "/");
|
|
strcat(path, UDNFUNC_FILENAME);
|
|
|
|
/* Read the udn node type name from the file */
|
|
status = read_udn_type_name(path, &node_name);
|
|
|
|
/* Transfer the names into the node_info structure */
|
|
if(status == OK) {
|
|
node_info[i].node_name = node_name;
|
|
}
|
|
else {
|
|
all_found = FALSE;
|
|
sprintf(msg, "ERROR - Problems reading %s in directory %s",
|
|
UDNFUNC_FILENAME, node_info[i].path_name);
|
|
print_error(msg);
|
|
}
|
|
}
|
|
|
|
if(all_found)
|
|
return(OK);
|
|
else
|
|
return(ERROR);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* *********************************************************************** */
|
|
|
|
|
|
/*
|
|
check_uniqueness
|
|
|
|
Function check_uniqueness determines if model names and function
|
|
names are unique with respect to each other and to the models and
|
|
functions internal to SPICE 3C1.
|
|
*/
|
|
|
|
static Status_t check_uniqueness(
|
|
int num_models, /* Number of model pathnames */
|
|
Model_Info_t *model_info, /* Info about each model */
|
|
int num_nodes, /* Number of node type pathnames */
|
|
Node_Info_t *node_info /* Info about each node type */
|
|
)
|
|
{
|
|
int i; /* A temporary counter */
|
|
int j; /* A temporary counter */
|
|
char msg[MAX_PATH_LEN+257]; /* space for an error message */
|
|
Boolean_t all_unique; /* true if names are unique */
|
|
|
|
/* Define a list of model names used internally by XSPICE */
|
|
/* These names (except 'poly') are defined in src/sim/INP/INPdomodel.c and */
|
|
/* are case insensitive */
|
|
static char *SPICEmodel[] = { "npn",
|
|
"pnp",
|
|
"d",
|
|
"njf",
|
|
"pjf",
|
|
"nmf",
|
|
"pmf",
|
|
"urc",
|
|
"nmos",
|
|
"pmos",
|
|
"r",
|
|
"c",
|
|
"sw",
|
|
"csw",
|
|
"poly" };
|
|
static int numSPICEmodels = sizeof(SPICEmodel) / sizeof(char *);
|
|
|
|
|
|
/* Define a list of node type names used internally by the simulator */
|
|
/* These names are defined in src/sim/include/MIFtypes.h and are case */
|
|
/* insensitive */
|
|
static char *UDNidentifier[] = { "v",
|
|
"vd",
|
|
"i",
|
|
"id",
|
|
"vnam",
|
|
"g",
|
|
"gd",
|
|
"h",
|
|
"hd",
|
|
"d" };
|
|
static int numUDNidentifiers = sizeof(UDNidentifier) / sizeof(char *);
|
|
|
|
|
|
|
|
/* First, normalize case of all model and node names to lower since */
|
|
/* SPICE is case insensitive in parsing decks */
|
|
for(i = 0; i < num_models; i++)
|
|
str_to_lower(model_info[i].spice_name);
|
|
for(i = 0; i < num_nodes; i++)
|
|
str_to_lower(node_info[i].node_name);
|
|
|
|
/* Then, loop through all model names and report errors if same as SPICE */
|
|
/* model name or same as another model name in list */
|
|
for(i = 0, all_unique = TRUE; i < num_models; i++) {
|
|
|
|
/* First check against list of SPICE internal names */
|
|
for(j = 0; j < numSPICEmodels; j++) {
|
|
if(strcmp(model_info[i].spice_name, SPICEmodel[j]) == 0) {
|
|
all_unique = FALSE;
|
|
sprintf(msg,
|
|
"ERROR - Model name '%s' is same as internal SPICE model name\n",
|
|
model_info[i].spice_name);
|
|
print_error(msg);
|
|
}
|
|
}
|
|
|
|
/* Skip if already seen once */
|
|
if(model_info[i].spice_unique == FALSE)
|
|
continue;
|
|
|
|
/* Then check against other names in list */
|
|
for(j = 0; j < num_models; j++) {
|
|
|
|
/* Skip checking against itself */
|
|
if(i == j)
|
|
continue;
|
|
|
|
/* Compare the names */
|
|
if(strcmp(model_info[i].spice_name, model_info[j].spice_name) == 0) {
|
|
all_unique = FALSE;
|
|
model_info[i].spice_unique = FALSE;
|
|
model_info[j].spice_unique = FALSE;
|
|
sprintf(msg,
|
|
"ERROR - Model name '%s' in directory: %s",
|
|
model_info[i].spice_name,
|
|
model_info[i].path_name);
|
|
print_error(msg);
|
|
print_error(" is same as");
|
|
sprintf(msg,
|
|
" model name '%s' in directory: %s\n",
|
|
model_info[j].spice_name,
|
|
model_info[j].path_name);
|
|
print_error(msg);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/* Loop through all C function names and report errors if duplicates found */
|
|
for(i = 0; i < num_models; i++) {
|
|
|
|
/* Skip if already seen once */
|
|
if(model_info[i].cfunc_unique == FALSE)
|
|
continue;
|
|
|
|
/* Check against other names in list only, not against SPICE identifiers */
|
|
/* Let linker catch collisions with SPICE identifiers for now */
|
|
for(j = 0; j < num_models; j++) {
|
|
|
|
/* Skip checking against itself */
|
|
if(i == j)
|
|
continue;
|
|
|
|
/* Compare the names */
|
|
if(strcmp(model_info[i].cfunc_name, model_info[j].cfunc_name) == 0) {
|
|
all_unique = FALSE;
|
|
model_info[i].cfunc_unique = FALSE;
|
|
model_info[j].cfunc_unique = FALSE;
|
|
sprintf(msg,
|
|
"ERROR - C function name '%s' in directory: %s",
|
|
model_info[i].cfunc_name,
|
|
model_info[i].path_name);
|
|
print_error(msg);
|
|
print_error(" is same as");
|
|
sprintf(msg,
|
|
" C function name '%s' in directory: %s\n",
|
|
model_info[j].cfunc_name,
|
|
model_info[j].path_name);
|
|
print_error(msg);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/* Loop through all node type names and report errors if same as internal */
|
|
/* name or same as another name in list */
|
|
for(i = 0; i < num_nodes; i++) {
|
|
|
|
/* First check against list of internal names */
|
|
for(j = 0; j < numUDNidentifiers; j++) {
|
|
if(strcmp(node_info[i].node_name, UDNidentifier[j]) == 0) {
|
|
all_unique = FALSE;
|
|
sprintf(msg,
|
|
"ERROR - Node type '%s' is same as internal node type\n",
|
|
node_info[i].node_name);
|
|
print_error(msg);
|
|
}
|
|
}
|
|
|
|
/* Skip if already seen once */
|
|
if(node_info[i].unique == FALSE)
|
|
continue;
|
|
|
|
/* Then check against other names in list */
|
|
for(j = 0; j < num_nodes; j++) {
|
|
|
|
/* Skip checking against itself */
|
|
if(i == j)
|
|
continue;
|
|
|
|
/* Compare the names */
|
|
if(strcmp(node_info[i].node_name, node_info[j].node_name) == 0) {
|
|
all_unique = FALSE;
|
|
node_info[i].unique = FALSE;
|
|
node_info[j].unique = FALSE;
|
|
sprintf(msg,
|
|
"ERROR - Node type '%s' in directory: %s",
|
|
node_info[i].node_name,
|
|
node_info[i].path_name);
|
|
print_error(msg);
|
|
print_error(" is same as");
|
|
sprintf(msg,
|
|
" node type '%s' in directory: %s\n",
|
|
node_info[j].node_name,
|
|
node_info[j].path_name);
|
|
print_error(msg);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* Return error status */
|
|
if(all_unique)
|
|
return(OK);
|
|
else
|
|
return(ERROR);
|
|
|
|
}
|
|
|
|
|
|
/* *********************************************************************** */
|
|
|
|
|
|
/*
|
|
write_CMextrn
|
|
|
|
Function write_CMextrn writes the CMextrn.h file used in
|
|
compiling SPIinit.c immediately prior to linking the simulator
|
|
and code models. This SPICE source file uses the structures
|
|
mentioned in the include file to define the models known to the
|
|
simulator.
|
|
*/
|
|
|
|
static Status_t write_CMextrn(
|
|
int num_models, /* Number of model pathnames */
|
|
Model_Info_t *model_info /* Info about each model */
|
|
)
|
|
{
|
|
int i; /* A temporary counter */
|
|
FILE *fp; /* File pointer for writing CMextrn.h */
|
|
|
|
|
|
/* Open the file to be written */
|
|
fp = fopen("cmextrn.h", "w");
|
|
if(fp == NULL) {
|
|
print_error("ERROR - Problems opening CMextrn.h for write");
|
|
return(ERROR);
|
|
}
|
|
|
|
/* Write out the data */
|
|
for(i = 0; i < num_models; i++) {
|
|
fprintf(fp, "extern SPICEdev %s_info;\n", model_info[i].cfunc_name);
|
|
}
|
|
|
|
/* Close the file and return */
|
|
fclose(fp);
|
|
return(OK);
|
|
}
|
|
|
|
|
|
/* *********************************************************************** */
|
|
|
|
|
|
/*
|
|
write_CMinfo
|
|
|
|
Function write_CMinfo writes the CMinfo.h file used in compiling
|
|
SPIinit.c immediately prior to linking the simulator and code
|
|
models. This SPICE source file uses the structures mentioned in
|
|
the include file to define the models known to the simulator.
|
|
*/
|
|
|
|
|
|
static Status_t write_CMinfo(
|
|
int num_models, /* Number of model pathnames */
|
|
Model_Info_t *model_info /* Info about each model */
|
|
)
|
|
{
|
|
int i; /* A temporary counter */
|
|
FILE *fp; /* File pointer for writing CMinfo.h */
|
|
|
|
|
|
/* Open the file to be written */
|
|
fp = fopen("cminfo.h", "w");
|
|
if(fp == NULL) {
|
|
print_error("ERROR - Problems opening CMinfo.h for write");
|
|
return(ERROR);
|
|
}
|
|
|
|
/* Write out the data */
|
|
for(i = 0; i < num_models; i++) {
|
|
fprintf(fp, "&%s_info,\n", model_info[i].cfunc_name);
|
|
}
|
|
|
|
/* Close the file and return */
|
|
fclose(fp);
|
|
return(OK);
|
|
}
|
|
|
|
|
|
|
|
/* *********************************************************************** */
|
|
|
|
|
|
|
|
/*
|
|
write_UDNextrn
|
|
|
|
Function write_UDNextrn writes the UDNextrn.h file used in
|
|
compiling SPIinit.c immediately prior to linking the simulator
|
|
and user-defined nodes. This SPICE source file uses the structures
|
|
mentioned in the include file to define the node types known to the
|
|
simulator.
|
|
*/
|
|
|
|
|
|
|
|
static Status_t write_UDNextrn(
|
|
int num_nodes, /* Number of node pathnames */
|
|
Node_Info_t *node_info /* Info about each node */
|
|
)
|
|
{
|
|
int i; /* A temporary counter */
|
|
FILE *fp; /* File pointer for writing UDNextrn.h */
|
|
|
|
|
|
/* Open the file to be written */
|
|
fp = fopen("udnextrn.h", "w");
|
|
if(fp == NULL) {
|
|
print_error("ERROR - Problems opening UDNextrn.h for write");
|
|
return(ERROR);
|
|
}
|
|
|
|
/* Write out the data */
|
|
for(i = 0; i < num_nodes; i++) {
|
|
fprintf(fp, "extern Evt_Udn_Info_t udn_%s_info;\n", node_info[i].node_name);
|
|
}
|
|
|
|
/* Close the file and return */
|
|
fclose(fp);
|
|
return(OK);
|
|
}
|
|
|
|
|
|
/* *********************************************************************** */
|
|
|
|
|
|
/*
|
|
write_UDNinfo
|
|
|
|
Function write_UDNinfo writes the UDNinfo.h file used in
|
|
compiling SPIinit.c immediately prior to linking the simulator
|
|
and user-defined nodes. This SPICE source file uses the structures
|
|
mentioned in the include file to define the node types known to the
|
|
simulator.
|
|
*/
|
|
|
|
|
|
|
|
static Status_t write_UDNinfo(
|
|
int num_nodes, /* Number of node pathnames */
|
|
Node_Info_t *node_info /* Info about each node */
|
|
)
|
|
{
|
|
int i; /* A temporary counter */
|
|
FILE *fp; /* File pointer for writing UDNinfo.h */
|
|
|
|
|
|
/* Open the file to be written */
|
|
fp = fopen("udninfo.h", "w");
|
|
if(fp == NULL) {
|
|
print_error("ERROR - Problems opening UDNinfo.h for write");
|
|
return(ERROR);
|
|
}
|
|
|
|
/* Write out the data */
|
|
for(i = 0; i < num_nodes; i++) {
|
|
fprintf(fp, "&udn_%s_info,\n", node_info[i].node_name);
|
|
}
|
|
|
|
/* Close the file and return */
|
|
fclose(fp);
|
|
return(OK);
|
|
}
|
|
|
|
|
|
/* *********************************************************************** */
|
|
|
|
/*
|
|
write_objects_inc
|
|
|
|
Function write_objects_inc writes a make include file used by
|
|
the make utility to locate the object modules needed to link the
|
|
simulator with the code models and user-defined node types.
|
|
*/
|
|
|
|
static Status_t write_objects_inc(
|
|
int num_models, /* Number of model pathnames */
|
|
Model_Info_t *model_info, /* Info about each model */
|
|
int num_nodes, /* Number of udn pathnames */
|
|
Node_Info_t *node_info /* Info about each node type */
|
|
)
|
|
{
|
|
int i; /* A temporary counter */
|
|
FILE *fp; /* File pointer for writing make_include */
|
|
|
|
|
|
/* Open the file to be written */
|
|
fp = fopen("objects.inc", "w");
|
|
if(fp == NULL) {
|
|
print_error("ERROR - Problems opening objects.inc file for write");
|
|
return(ERROR);
|
|
}
|
|
|
|
/* Write out the data */
|
|
for(i = 0; i < num_models; i++) {
|
|
fprintf(fp, "%s/*.o", model_info[i].path_name);
|
|
if((i < (num_models - 1)) || (num_nodes > 0))
|
|
fprintf(fp, " \\\n");
|
|
else
|
|
fprintf(fp, "\n");
|
|
}
|
|
for(i = 0; i < num_nodes; i++) {
|
|
fprintf(fp, "%s/*.o", node_info[i].path_name);
|
|
if(i < (num_nodes - 1))
|
|
fprintf(fp, " \\\n");
|
|
else
|
|
fprintf(fp, "\n");
|
|
}
|
|
|
|
/* Close the file and return */
|
|
fclose(fp);
|
|
return(OK);
|
|
}
|
|
|
|
|
|
/*
|
|
read_udn_type_name
|
|
|
|
This function reads a User-Defined Node Definition File until
|
|
the definition of the Evt_Udn_Info_t struct
|
|
is found, and then gets the name of the node type from the first
|
|
member of the structure.
|
|
*/
|
|
|
|
static Status_t read_udn_type_name(
|
|
char *path, /* the path to the node definition file */
|
|
char **node_name /* the node type name found in the file */
|
|
)
|
|
{
|
|
FILE *fp; /* file pointer for opened file */
|
|
/*char msg[MAX_PATH_LEN+257];*/ /* space for an error message */
|
|
Boolean_t found; /* true if name found successfully */
|
|
Boolean_t in_struct; /* true if found struct with name */
|
|
char name[MAX_NAME_LEN + 1]; /* temporary storage for name read */
|
|
int c; /* a character read from the file */
|
|
int i; /* a counter */
|
|
|
|
static char *struct_type = "Evt_Udn_Info_t";
|
|
|
|
/* Open the file from which the node type name will be read */
|
|
fp = fopen(path, "r");
|
|
if(fp == NULL)
|
|
return(ERROR);
|
|
|
|
/* Read the file until the definition of the Evt_Udn_Info_t struct */
|
|
/* is found, then get the name of the node type from the first */
|
|
/* member of the structure */
|
|
found = FALSE;
|
|
do {
|
|
/* read the next character */
|
|
c = fgetc(fp);
|
|
|
|
/* check for and gobble up comments */
|
|
if(c == '/') {
|
|
c = fgetc(fp);
|
|
if(c == '*') {
|
|
do {
|
|
c = fgetc(fp);
|
|
if(c == '*') {
|
|
c = fgetc(fp);
|
|
if((c == '/') || (c == EOF))
|
|
break;
|
|
else
|
|
ungetc(c, fp);
|
|
}
|
|
} while(c != EOF);
|
|
}
|
|
}
|
|
if(c == EOF)
|
|
break;
|
|
|
|
/* read until "Evt_Udn_Info_t" is encountered */
|
|
for(i = 0, in_struct = FALSE; ; i++) {
|
|
if(c != struct_type[i])
|
|
break;
|
|
else if(i == (sizeof(struct_type) - 2)) {
|
|
in_struct = TRUE;
|
|
break;
|
|
}
|
|
else
|
|
c = fgetc(fp);
|
|
}
|
|
/* if found it, read until open quote found */
|
|
/* and then read the name until the closing quote is found */
|
|
if(in_struct) {
|
|
do {
|
|
c = fgetc(fp);
|
|
if(c == '"') {
|
|
i = 0;
|
|
do {
|
|
c = fgetc(fp);
|
|
if(c == '"') {
|
|
found = TRUE;
|
|
name[i] = '\0';
|
|
}
|
|
else if(c != EOF)
|
|
name[i++] = c;
|
|
} while((c != EOF) && (! found));
|
|
}
|
|
} while((c != EOF) && (! found));
|
|
}
|
|
|
|
} while((c != EOF) && (! found));
|
|
|
|
/* Close the file and return */
|
|
fclose(fp);
|
|
|
|
if(found) {
|
|
*node_name = (char *) malloc(strlen(name) + 1);
|
|
strcpy(*node_name, name);
|
|
return(OK);
|
|
}
|
|
else {
|
|
*node_name = NULL;
|
|
return(ERROR);
|
|
}
|
|
}
|
|
|