Features of the SmartSpice Interpreter

Introduction

The Interpreter is a completely integrated feature of SmartSpice. It is most frequently used to introduce new user-defined models into SmartSpice. These models can then by called directly from an input deck in the same manner as any other internal SmartSpice model. In addition to providing this advanced modeling capability, it is possible to call interpreted commands directly from the SmartSpice command line. When used in this manner, the interpreter can provide a sophisticated simulation control mechanism, as illustrated in Example I.

The interpreter is essentially a compiler that understands the C language syntax, its loops, statements and conditional constructs. Once a function has been interpreted, the resulting code is stored for future use during the simulation session. As a result there is little overhead when a function is repeatedly called, as is the case when device model are evaluated during simulation. Consequently, the SmartSpice Interpreter is extremely efficient and there is only a small difference between the simulation time consumed using the internal SmartSpice models and the interpreted models. Through interface functions provided by SmartSpice, it is possible for the interpreter to access and manipulate internal data-structures, thus allowing the user to create complicated pre/post-processing sequences. An example of how a device model can be implemented into SmartSpice using the Interpreter will be described in a future issue of the Simulation Standard.

In order to facilitate the development of interpreter code, SmartSpice provides an internal X-MOTIF based debugger, as shown in Figure 1. The debugger provides all the standard debugging facilities, e.g. it is possible to stop at a particular line, step through the code and print out variable values. This is especially important in the development phase of a device model, for example, when it is necessary to debug and verify the models internal behavior.

 

Figure 1. SmartSpice Interpreter Debugger.

Example I: Eye Diagram Generation

The circuit shown in Figure 2 represents a typical model of a receiver. Vin is the input to the circuit and Vout represents the output response of the circuit. The losses and frequency characteristics of the receiver are modeled using the RC elements shown. The transistor provides circuit gain. The input to the circuit is essentially a digital waveform with a fixed pulse width and some finite rise and fall time. A digital 1 is represented by +1V and 0 by 0V.

 

Figure 2. Receiver test circuit.

 

In general, to test a receiver circuit, a pseudo random sequence of 1's and 0's is used at the input source (Vin) and the response of the circuit (Vout) is plotted as an eye-diagram plot. An eye-diagram plot is a plot where the output signal (Vout) is divided up into fixed time periods which are then superimposed on each other. The result is a plot with many overlapping lines enclosing an empty space, known as the "eye". The quality of the receiver circuit is characterized by the dimensions of the eye. An open eye means that a detector will be able to distinguish between 1's and 0's on its input. A closed eye means that a detector placed on Vout is likely to give errors for certain input bit sequences.

The frequency response of the receiver is modeled by RC filters. A poor combination of capacitors and resistors will result in a circuit which exhibits both over and under shoot. The circuit shown in Figure 2 was simulated with three different values of the capacitance C2 (10pF, 50pF and 100pF) and the results plotted, as shown in Figure 3. As can be seen the result with the best "eye" is the circuit with C2 = 10pF. As the C2 capacitance is increased, the plot becomes progressively worse, with the "eye" decreasing in size and the over/under-shoot increasing.

 

Figure 3. Eye Diagram plots for 3 different C2 values (10pF, 50pF, and 100pF)

 

 

The interpreter code to simulate this circuit can be divided into 3 different stages;

Read a specification file, that contains details of the input pulse (Vin), the pulse width, the rise and fall times, and the pseudo-random bit sequence.

Convert this file into the SmartSpice piecewise linear format for use by the Vin source.

Source the input deck.

Create a transient simulation command and execute it.

Get the resulting "time" vector and split the vector into time periods.

Plot the circuit output using the newly created "split_time" variable as the x-axis.

The main function of the interpreted code is shown in Figure 4 with the code for the spilt_time_vector_into_periods function given in Figure 5. The algorithm basically follows the sequence given above. Interface functions such as "get_vector", "command" and "make_vector" allow the interpreted program to access internal SmartSpice commands and data structures. While in this case, the interpreted program performs all parts of the simulation process (pre-processing, simulation and post-processing), interpreted functions can be called at any stage to perform a particular action. Hence, for example, it is possible to create functions to perform certain postprocessing activities automatically and these can be called from the SmartSpice command line once simulation is complete.

 

int eye_diagram (num_arguments, argument_string)
int num_arguments;
char *argument_string;
{  
	int ret;  
	int len;  
	double endtime;  
	double period;  
	char comstr[100];  
	double *split_time;  
	double *time;  
if (num_arguments != 0) return (1);
/* Create the input pwl waveform. */  
ret = create_pwl_pulse_sequence ("pulse data", 
	 "pwl pulses",
	 &endtime, &period);
if (ret) return (1);  
/* Source the test input deck. */  
command ("source eye_test.inp");  
/* Create and execute the transient analysis. */  
sprintf (comstr, "tran 1n %g", endtime);  
command (comstr);  
/* Get the resulting time vector and split it      
	into periods based upon 
the pulse width of the input signal.*/ 
time = get_vector ("time",&len);  
if (time == NULL) return (1);  
split_time = split_time_vector_into_periods 
				(period, time, len);  
/* Create the new vector "split_time" in the current plot.
Plot Vout against this vector. */  
ret = make vector ("split_time", split_time, len);  
command ("plot v(out) vs split_time discont"); 
/* End of function. */  
return(0);
}

Figure 4. Main function in the Eye Diagram code.

 

/* 
 * The purpose of the function is to take 
 * a time vector
 * and to create another time vector  
 * where the time is  
 * reset back to zero after every 'period' 
 * seconds. When another vector is 
 * plotted against this new time vector 
 * the data will overlay itself after 
 * every 'period' seconds.  The result 
 * will appear like an eye diagram plot. 
 */

double *split_time_vector_into_periods 
(period,timevect,len)
double period;
double *timevect;
int len;
{
  int i;  
  double offset;  
  double *splittime;  

/*
 * Allocate some memory for the adjusted time vector.
 */  
splittime = (double *) malloc ((len + 1) * 
sizeof (double));  
if (splittime == NULL) return (NULL);

offset = 0.0;

for (i = 0; i < len; i++)  
{
 if ((timevect[i] - offset) >= period)
  offset = off set + period;    
 splittime[i] = timevect[i] - offset; 
}
 return (splittime);
}

Figure 5. Interpreter colde for the spilt_time_vector_into_periods fuctions

 

Conclusion

In this article, some of the features of the SmartSpice Interpreter have been discussed. The Interpreter can be used to introduce user-defined models into SmartSpice (the subject of a future Simulation Standard article) and to provide advanced pre/post-processing functionality as demonstrated in Example I. As can be seen from the code in the example functions, the Interpreter accepts standard C-language syntax. SmartSpice provides interface functions which allows internal data structures and procedures to be accessed from within the user's interpreted code possible to compile the model code using a standard C compiler and insert the model into a dynamic library. This dynamic library will then be loaded by SmartSpice when the user-defined model is accessed. Since the code will have been compiled, the model will execute much quicker and simulation time will be reduced Hence the use of interpreter and dynamic libraries provides both a user-friendly model development environment and fast model execution.