Subject: Re: curve merging

From: Syed Huq <[email-masked]>
Date: Wed, 9 Dec 1998 21:31:50 -0800 (PST)

Hi,

Yes it can be done with Xemacs. It's called 'Rectangle Operations' and I
think you could try the following key bindings:

^x r k, ^x r y, ^x r d	

emacs or Xemacs is a GNU editor(plus more)found on all Linux systems as 
well as UNIX.

Regards,
Syed
Cisco Systems, Inc.

> From [email-masked] Tue Dec  8 08:06:46 1998
> X-SMAP-Received-From: outside
> Date: Tue, 8 Dec 98 09:16 CST
> From: [email-masked] (Weston Beal)
> To: [email-masked]
> Subject: curve merging
> 
> Dear Users,
> 
> I have two IBIS files which represent the min and max cases of a
> model.  One file has the min characteristics in the typ column and the
> other has the max characteristics in the typ column.  I would like to
> merge them into one file in standard (typ, min, max) IBIS format.  Does
> anyone have a utility to do this which they can share?
> 
> Thanks,
> Weston Beal

---

From: "R.Sanjeev" <[email-masked]>
Date: Fri, 11 Dec 1998 13:34:36 +0530

Hi Beal,

I picked out the parts of the s2ibis code that does this merging. It'll work
for data files generated for the following types of spice:
                                "HSpice",
                                "PSpice",
                                "SPICE2",
                                "Spice3",
                                "Spectre"
I've added a spice type called "dummy" if you just have files with data and
nothing else.
(The first line of the input files should be empty)

if you are using spice other than these you need to add the following to the
code to take care of it:
1. spiceNameString :           your spice name(does not run it so just
something
                                             different from those already
there)
2. dataEndMarker :              When to stop reading the data in the file.
3. VIDataBeginMarker:       Where to start reading from the file for actual
data points.
4. VIDataConversionString: What format will the data be in(check the code
for examples)

The format to use it right now is:
combine <spiceType> <typFl> <minFl> <maxFl> <opFl>

Copy the two files in a dir and say make(in any Unix platform) on windows
just compile the combine.c

Please let me know if there are any problems.

regards,
presi
-----

--
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Cahn's Axiom: "When all else fails, read the instructions."
R.Sanjeev                   Home...
~~~~~~~~~                   hppt://members.tripod.com/~r_sanjeev
e-mail:    [email-masked]
snail-mail:
           20, Karnan Street, Murugesha Naicken Nagar,
           Kodambakkam, Chennai-24.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

#
# makefile for mergeIBIS
#
##############################################################################
# Compilation and linking using GNU tools
#
CC = gcc
CFLAGS = -g
##############################################################################

PROGRAM = mergeIBIS

SRCS = mergeIBIS.c

ALL = $(SRCS) 

OBJS  =$(SRCS:.c=.o)

$(PROGRAM): $(OBJS)
	$(CC) -o $(PROGRAM) $(CFLAGS) $(OBJS)
	
clean :
	rm $(OBJS) $(PROGRAM)
depend	:
	makedepend -- $(CFLAGS)   $(SRCS)

# DO NOT DELETE THIS LINE -- make depend depends on it.
/********************************************************************
*                   Parts from s2ibis2 that came from:
*					North Carolina State University
*					Electronics Research Laboratory
*
*                   Modified by: Sanjeev Ranganathan
*                   Indian Institute of Technology Madras
*                   VLSI Design Laboratory.
*                   e-mail: [email-masked]
********************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

/*
 * ARGUMENT LABELS
 *
 * These are used to label function arguments.
 *
 * IN indicates that the argument data is read only by the function, and 
 * not written.
 *
 * INOUT indicates that the argument data is read and written by the
 * function.
 *
 * OUT indicates that the argument data is written by the function,
 * without reference to its previous value.
 *
 * INOUT and OUT apply only to pointer arguments, since there is no
 * direct pass-by-reference mechanism in C.
 */
#define	IN
#define OUT
#define INOUT
#define SHARED

/* MAX TABLE size :used as initial value*/
#define MAX_TAB_SIZE  600

/* Basic data Structures required a minTypMax table and its size */
typedef struct {
	double			typ,			/* typical value */
					min,			/* minimum value */
					max;			/* maximum value */
} ibisTypMinMax_t, *ibisTypMinMax_Pt;

typedef struct VIentryDef {
	double			v;
	ibisTypMinMax_t	i;
} ibisVItableEntry_t, *ibisVItableEntry_Pt;

typedef struct {
	int				size;
    ibisVItableEntry_Pt 
					VIs;
} ibisVItable_t, *ibisVItable_Pt;

/* The Kind of Spices that it can support */

char	*spiceNameString[] = 
				{
				"HSpice",
				"PSpice",
				"SPICE2",
				"Spice3",
				"Spectre",
				"dummy"
				};
/* The number of these */
#define NUM_SUPP_SPICE 6
/* It uses the following as the data begin marker i.e. these are present in 
 * the line before the data is actually displayed */
char	*VIDataBeginMarker[] = 
				{
				"transfer",
				"DC TRANSFER",
				"X",
				"Index",
				"Values",
				"\n"
				};

/* Stops reading with this */
char	*dataEndMarker[] =
				{
				"job",
				"",
				"Y",
				"CPU",
				"",
				"eof"
				};
                
/* The data is assumed to be %le and is read as that */                
char	*VIDataConversionString[] =
				{
				"%le %le \n",
				"%le %le \n",
				"%le %le \n",
				"%*d %le %le \n",
				"%*d %le %*le %le \n",
				"%le %le \n"
				};
        
/* Maps the given input name to an integer corresponding to that name */
int 
find_spice_type(char *spName)
{
  int i;
  for (i=0;i<NUM_SUPP_SPICE;i++)
    if (!strcmp(spName,spiceNameString[i]))
        return(i);
   
  return(0);
}

/* reads the typ min max files and generates the data-structure */
int
getSpiceVIData(	IN	ibisVItable_Pt 	VIData_P,
				IN	int				tableSize,
				IN	int				spiceType,
				IN	char			*spiceOutFile,
				IN	char			*command )
{
FILE	*outFile_P = NULL;
char	lineBuffer[256];
double	tempData[300][2];
int		rowIndex = 1,i = 0;

if ( ( outFile_P = fopen( spiceOutFile, "r" ) ) == NULL )
	{
	fprintf( stderr, "Unable to open file %s for reading.\n",
			 spiceOutFile );
	return( 1 );
	}

/*------------------------------------------------------------------------
*
*	Read lines until we hit the data begin marker or EOF.  If it's EOF, 
*	return an error.
*
*-----------------------------------------------------------------------*/
while ( ( fgets( lineBuffer, 256, outFile_P ) != NULL ) &&
		( strstr( lineBuffer, VIDataBeginMarker[spiceType] ) == NULL ) );

if ( strstr( lineBuffer, VIDataBeginMarker[spiceType] ) == NULL )
	{
	fprintf( stderr, "Data begin marker %s not found ",
			 VIDataBeginMarker[spiceType] );
	fprintf( stderr, "in output file %s.\n", spiceOutFile );
	return( 1 );
	}

/*------------------------------------------------------------------------
*
*	We're now at the line before the start of the VI data.  
*	Read lines until we get the correct number of columns.
*
*-----------------------------------------------------------------------*/
while ( ( fgets( lineBuffer, 256, outFile_P ) != NULL ) &&
		( sscanf( lineBuffer, VIDataConversionString[spiceType], 
				  &tempData[0][0], &tempData[0][1] ) != 2 ) );

if ( feof( outFile_P ) )
	{
	fprintf( stderr, "s2ibis2: No data in file %s\n", spiceOutFile );
	return( 1 );
	}

tempData[0][1] = -tempData[0][1];

/*------------------------------------------------------------------------
*
*	Now we read until we see the end-of-data marker or the end-of-file 
*	marker.  We include the data from any read that returns the correct 
*	number of columns read.  If we don't have an end-of-data marker for
*	this particular flavor of Spice, we just read to the end-of-file maker.
*
*-----------------------------------------------------------------------*/
if ( dataEndMarker[spiceType] == NULL )
	{
	while ( ( fgets( lineBuffer, 256, outFile_P ) != NULL ) )
		if ( sscanf(lineBuffer, VIDataConversionString[spiceType],
		   &tempData[rowIndex][0], &tempData[rowIndex][1]) == 2 )
			{
			tempData[rowIndex][1] = -tempData[rowIndex][1];
			rowIndex++;
			}
	}
else
	{
	while ( ( fgets( lineBuffer, 256, outFile_P ) != NULL ) &&
			( strstr( lineBuffer, dataEndMarker[spiceType] ) == NULL ) ) 
		if ( sscanf(lineBuffer, VIDataConversionString[spiceType],
		   &tempData[rowIndex][0], &tempData[rowIndex][1]) == 2 )
			{
			tempData[rowIndex][1] = -tempData[rowIndex][1];
			rowIndex++;
			}
	}

fclose( outFile_P );

rowIndex--;
if ( rowIndex > tableSize )
	{
	fprintf( stderr, "s2ibis2: Spice job returned too many data points.\n" );
	fprintf( stderr, "         May have to truncate table...\n" );
	}

/*------------------------------------------------------------------------
*
*	Now we transfer the data to the correct place, depending on the value
*	of command.
*
*-----------------------------------------------------------------------*/
if ( !( strcmp( command, "typ" ) ) )
{
	VIData_P->size = rowIndex + 1;
    /** Some way to create the size equivalent for the rowindex **/
	if( (VIData_P->VIs = (ibisVItableEntry_Pt) \
         malloc(sizeof(ibisVItableEntry_t) * VIData_P->size) ) == NULL)
    {
         printf("Out of memory");
         return(1);
    }        
    for ( i = 0; i <= rowIndex; i++ )
	{
		VIData_P->VIs[i].v = tempData[i][0];
		VIData_P->VIs[i].i.typ = tempData[i][1];
	}
}
else if ( !( strcmp( command, "min" ) ) )
	for ( i = 0; i <= rowIndex; i++ )
		VIData_P->VIs[i].i.min = tempData[i][1];
else
	for ( i = 0; i <= rowIndex; i++ )
		VIData_P->VIs[i].i.max = tempData[i][1];

return( 0 );
}

/* Does the final write into the Outfile of the Data Structure generated
 * earlier by getSpiceVIData function */
int writeSpiceVIData(IN char* Outfile, IN ibisVItable_Pt VIData_P)
{
    FILE * outFile_P;
    int j = 0;
    
    if ( ( outFile_P = fopen( Outfile, "w" ) ) == NULL )
	{
	    fprintf( stderr, "Unable to open file %s for writing.\n",
			 outFile_P );
	    perror( "s2ibis2");
	    return( 1 );
	}
    printf("%s Generated by program\n",Outfile);
    fprintf(outFile_P,"| Voltage\t I(typ)\t I(min)\t I(max)\n");
    for(j = 0 ;j < VIData_P->size;j++)
        fprintf(outFile_P,"%le %le %le %le\n",VIData_P->VIs[j].v, \
        VIData_P->VIs[j].i.typ, \
        VIData_P->VIs[j].i.min,VIData_P->VIs[j].i.max);
    fclose(outFile_P);
}
int 
main(int argc,char* argv[])
{
    /* Take the input and call get Spice VI Data in proper order 
    to get all the data required and then print quietly */
    ibisVItable_Pt 	VIData_P ;
    int spiceType;
    if (argc<2) 
    {
        printf("Usage %s <spiceType> <typFl> <minFl> <maxFl> <opFl>\n",argv[0]);
        return(1);
    }
    spiceType = find_spice_type(argv[1]);    
    getSpiceVIData(VIData_P,MAX_TAB_SIZE,spiceType,argv[2],"typ");
    getSpiceVIData(VIData_P,VIData_P->size,spiceType,argv[3],"min");
    getSpiceVIData(VIData_P,VIData_P->size,spiceType,argv[4],"max");
    writeSpiceVIData(argv[5],VIData_P);
}