Add more comments. Move incompatible input name checks to add_..._inout_timing_model() functions for dff, jkff, dltch.
This commit is contained in:
parent
112e47d0d3
commit
5a50868264
|
|
@ -15,7 +15,7 @@
|
|||
are estimated. Pspice has a rich set of timing simulation features,
|
||||
such as checks for setup/hold violations, minimum pulse width, and
|
||||
hazard detection.
|
||||
Only the common logic gates, flip-flops, and latches are suported.
|
||||
Only the common logic gates, flip-flops, and latches are supported.
|
||||
|
||||
First pass through a subcircuit. Call initialize_udevice() and read the
|
||||
.model cards by calling u_process_model_line() (or similar) for each card,
|
||||
|
|
@ -32,9 +32,12 @@
|
|||
gen_..._instance(). Creating new cards to replace the U* and .model
|
||||
cards is done by calling replacement_udevice_cards(), which returns a
|
||||
list of new cards. The list of cards is then to be inserted after the
|
||||
.subckt card and before the .ends card. This occurs in the function
|
||||
u_instances() in frontend/inpcom.c. Finally, call cleanup_udevice()
|
||||
before repeating the sequence for another subcircuit.
|
||||
.subckt card and before the .ends card. This occurs in the driver
|
||||
function u_instances() in frontend/inpcom.c.
|
||||
Finally, call cleanup_udevice() before repeating the sequence for
|
||||
another subcircuit.
|
||||
|
||||
More explanations are provided below in comments with NOTE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
|
@ -184,8 +187,12 @@ struct timing_data {
|
|||
int estimate;
|
||||
};
|
||||
|
||||
/*
|
||||
Pin lists for inputs, outputs, tristate outputs.
|
||||
/* NOTE
|
||||
Pin lists contain the names of instance inputs, outputs, tristate outputs.
|
||||
These pin_lists are created by add_..._pin() calls within the various
|
||||
gen_..._instance() calls. When a .subckt ... .ends sequence is completed,
|
||||
create_ports_list() can be called to determine the IN/OUT/INOUT directions
|
||||
of the subckt ports.
|
||||
*/
|
||||
#define DIR_UNKNOWN 0
|
||||
#define DIR_IN 1
|
||||
|
|
@ -569,10 +576,14 @@ static char *find_xspice_for_delay(char *itype)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
/* NOTE
|
||||
Xlator and Xlate
|
||||
Xlate struct data is stored in an Xlatorp list struct
|
||||
Used to save translated instance and model statements
|
||||
Xlate struct data is stored in an Xlator list struct.
|
||||
Used to save translated instance and model statements.
|
||||
After an Xlator has been created, Xlate data is generated via
|
||||
create_xlate() and entered into the Xlator by add_xlator().
|
||||
A first_xlator() ... next_xlator() iteration loop will retrieve
|
||||
the Xlate data entries in an Xlator.
|
||||
*/
|
||||
static void delete_xlate(Xlatep p)
|
||||
{
|
||||
|
|
@ -628,7 +639,7 @@ static void print_xlate(Xlatep xp)
|
|||
printf("translated %s\n", xp->translated);
|
||||
printf("delays %s\n", xp->delays);
|
||||
printf("utype %s ", xp->utype);
|
||||
printf("xspixe %s ", xp->xspice);
|
||||
printf("xspice %s ", xp->xspice);
|
||||
printf("tmodel %s ", xp->tmodel);
|
||||
printf("mname %s\n", xp->mname);
|
||||
}
|
||||
|
|
@ -754,7 +765,11 @@ static void interpret_xlator(Xlatorp xp, BOOL brief)
|
|||
|
||||
/* static Xlatorp for collecting timing model delays */
|
||||
static Xlatorp model_xlatorp = NULL;
|
||||
|
||||
/* static Xlatorp for default zero delay models */
|
||||
static Xlatorp default_models = NULL;
|
||||
|
||||
/* static Xlatorp for storing translated instance and model statements */
|
||||
static Xlatorp translated_p = NULL;
|
||||
|
||||
static void create_translated_xlator(void)
|
||||
|
|
@ -773,6 +788,11 @@ static void cleanup_translated_xlator(void)
|
|||
translated_p = NULL;
|
||||
}
|
||||
|
||||
/* NOTE
|
||||
replacement_udevice_cards() is called by the driver function u_instances()
|
||||
in frontend/inpcom.c so that the new Xspice instance and model statements
|
||||
can be spliced into the card deck.
|
||||
*/
|
||||
struct card *replacement_udevice_cards(void)
|
||||
{
|
||||
struct card *newcard = NULL, *nextcard = NULL;
|
||||
|
|
@ -794,12 +814,6 @@ struct card *replacement_udevice_cards(void)
|
|||
nextcard = insert_new_line(nextcard, new_str, 0, 0);
|
||||
}
|
||||
}
|
||||
/*
|
||||
for (card = newcard; card; card = card->nextcard) {
|
||||
char* cut_line = card->line;
|
||||
printf("NEW CARD: %s\n", cut_line);
|
||||
}
|
||||
*/
|
||||
return newcard;
|
||||
}
|
||||
|
||||
|
|
@ -1079,6 +1093,15 @@ static void delete_instance_hdr(struct instance_hdr *hdr)
|
|||
return;
|
||||
}
|
||||
|
||||
/* NOTE
|
||||
There are translate_...() functions for each instance type (gates, arrays
|
||||
of gates, compound gates, dff, jkff, dltch).
|
||||
For each type (except pullup/down) an instance struct is created by calling
|
||||
the corresponding create_..._instance() then add_..._inout_timing_model()
|
||||
functions. The instance struct returned by add_..._inout_timing_model()
|
||||
is passed to the corresponding gen_..._instance() function, and the Xspice
|
||||
translations are stored in Xlator translated_p.
|
||||
*/
|
||||
static struct dff_instance *create_dff_instance(struct instance_hdr *hdrp)
|
||||
{
|
||||
struct dff_instance *dffip;
|
||||
|
|
@ -1457,15 +1480,6 @@ static Xlatorp gen_dff_instance(struct dff_instance *ip)
|
|||
qbarr = ip->qb_out;
|
||||
preb = ip->prebar;
|
||||
clrb = ip->clrbar;
|
||||
for (i = 0; i < num_gates; i++) {
|
||||
if (strncmp(darr[i], "$d_", 3) == 0) { return NULL; }
|
||||
}
|
||||
if (strcmp(preb, "$d_lo") == 0 || strcmp(preb, "$d_nc") == 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (strcmp(clrb, "$d_lo") == 0 || strcmp(clrb, "$d_nc") == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
xxp = create_xlator();
|
||||
add_input_pin(preb);
|
||||
|
|
@ -1543,16 +1557,6 @@ static Xlatorp gen_jkff_instance(struct jkff_instance *ip)
|
|||
qbarr = ip->qb_out;
|
||||
preb = ip->prebar;
|
||||
clrb = ip->clrbar;
|
||||
for (i = 0; i < num_gates; i++) {
|
||||
if (strncmp(jarr[i], "$d_", 3) == 0) { return NULL; }
|
||||
if (strncmp(karr[i], "$d_", 3) == 0) { return NULL; }
|
||||
}
|
||||
if (strcmp(preb, "$d_lo") == 0 || strcmp(preb, "$d_nc") == 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (strcmp(clrb, "$d_lo") == 0 || strcmp(clrb, "$d_nc") == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
xxp = create_xlator();
|
||||
add_input_pin(preb);
|
||||
|
|
@ -1632,15 +1636,6 @@ static Xlatorp gen_dltch_instance(struct dltch_instance *ip)
|
|||
qbarr = ip->qb_out;
|
||||
preb = ip->prebar;
|
||||
clrb = ip->clrbar;
|
||||
for (i = 0; i < num_gates; i++) {
|
||||
if (strncmp(darr[i], "$d_", 3) == 0) { return NULL; }
|
||||
}
|
||||
if (strcmp(preb, "$d_lo") == 0 || strcmp(preb, "$d_nc") == 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (strcmp(clrb, "$d_lo") == 0 || strcmp(clrb, "$d_nc") == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
xxp = create_xlator();
|
||||
add_input_pin(preb);
|
||||
|
|
@ -2280,6 +2275,12 @@ static char *get_estimate(struct timing_data *tdp)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/* NOTE
|
||||
The get_delays_...() functions calculate estimates of typical delays
|
||||
from the Pspice ugate, utgate, ueff, and ugff timing models.
|
||||
These functions are called from u_process_model(), and the delay strings
|
||||
are added to the timing model Xlator by add_delays_to_model_xlator().
|
||||
*/
|
||||
static char *get_delays_ugate(char *rem, char *d_name)
|
||||
{
|
||||
char *rising, *falling, *delays = NULL;
|
||||
|
|
@ -2467,18 +2468,6 @@ static char *get_delays_ugff(char *rem, char *d_name)
|
|||
return delays;
|
||||
}
|
||||
|
||||
/*
|
||||
static void print_delays(char *delays)
|
||||
{
|
||||
if (delays) {
|
||||
printf("<%s>\n", delays);
|
||||
} else {
|
||||
printf("<(null)>\n");
|
||||
}
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
static BOOL u_process_model(char *nline, char *original,
|
||||
char *newname, char *xspice)
|
||||
{
|
||||
|
|
@ -2589,6 +2578,26 @@ static struct dff_instance *add_dff_inout_timing_model(
|
|||
dffip->tmodel = TMALLOC(char, strlen(tok) + 1);
|
||||
(void) memcpy(dffip->tmodel, tok, strlen(tok) + 1);
|
||||
tfree(copyline);
|
||||
|
||||
/* Reject incompatible inputs */
|
||||
arrp = dffip->d_in;
|
||||
for (i = 0; i < num_gates; i++) {
|
||||
if (strncmp(arrp[i], "$d_", 3) == 0) {
|
||||
tfree(dffip);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if (strcmp(dffip->prebar, "$d_lo") == 0 ||
|
||||
strcmp(dffip->prebar, "$d_nc") == 0) {
|
||||
tfree(dffip);
|
||||
return NULL;
|
||||
}
|
||||
if (strcmp(dffip->clrbar, "$d_lo") == 0 ||
|
||||
strcmp(dffip->clrbar, "$d_nc") == 0) {
|
||||
tfree(dffip);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return dffip;
|
||||
}
|
||||
|
||||
|
|
@ -2646,6 +2655,25 @@ static struct dltch_instance *add_dltch_inout_timing_model(
|
|||
dlp->tmodel = TMALLOC(char, strlen(tok) + 1);
|
||||
(void) memcpy(dlp->tmodel, tok, strlen(tok) + 1);
|
||||
tfree(copyline);
|
||||
|
||||
/* Reject incompatible inputs */
|
||||
arrp = dlp->d_in;
|
||||
for (i = 0; i < num_gates; i++) {
|
||||
if (strncmp(arrp[i], "$d_", 3) == 0) {
|
||||
tfree(dlp);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if (strcmp(dlp->prebar, "$d_lo") == 0 ||
|
||||
strcmp(dlp->prebar, "$d_nc") == 0) {
|
||||
tfree(dlp);
|
||||
return NULL;
|
||||
}
|
||||
if (strcmp(dlp->clrbar, "$d_lo") == 0 ||
|
||||
strcmp(dlp->clrbar, "$d_nc") == 0) {
|
||||
tfree(dlp);
|
||||
return NULL;
|
||||
}
|
||||
return dlp;
|
||||
}
|
||||
|
||||
|
|
@ -2653,7 +2681,7 @@ static struct jkff_instance *add_jkff_inout_timing_model(
|
|||
struct instance_hdr *hdr, char *start)
|
||||
{
|
||||
char *tok, *copyline;
|
||||
char *name, **arrp;
|
||||
char *name, **arrp, **arrpk;
|
||||
int i, num_gates = hdr->num1;
|
||||
struct jkff_instance *jkffip = NULL;
|
||||
|
||||
|
|
@ -2712,6 +2740,27 @@ static struct jkff_instance *add_jkff_inout_timing_model(
|
|||
jkffip->tmodel = TMALLOC(char, strlen(tok) + 1);
|
||||
(void) memcpy(jkffip->tmodel, tok, strlen(tok) + 1);
|
||||
tfree(copyline);
|
||||
|
||||
/* Reject incompatible inputs */
|
||||
arrp = jkffip->j_in;
|
||||
arrpk = jkffip->k_in;
|
||||
for (i = 0; i < num_gates; i++) {
|
||||
if (strncmp(arrp[i], "$d_", 3) == 0 ||
|
||||
strncmp(arrpk[i], "$d_", 3) == 0) {
|
||||
tfree(jkffip);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if (strcmp(jkffip->prebar, "$d_lo") == 0 ||
|
||||
strcmp(jkffip->prebar, "$d_nc") == 0) {
|
||||
tfree(jkffip);
|
||||
return NULL;
|
||||
}
|
||||
if (strcmp(jkffip->clrbar, "$d_lo") == 0 ||
|
||||
strcmp(jkffip->clrbar, "$d_nc") == 0) {
|
||||
tfree(jkffip);
|
||||
return NULL;
|
||||
}
|
||||
return jkffip;
|
||||
}
|
||||
|
||||
|
|
@ -3070,6 +3119,11 @@ BOOL u_check_instance(char *line)
|
|||
}
|
||||
}
|
||||
|
||||
/* NOTE
|
||||
The input nline is expected to be a card in the deck which contains
|
||||
a Pspice u* instance statement with all the '+' continuations added
|
||||
minus the '+'.
|
||||
*/
|
||||
BOOL u_process_instance(char *nline)
|
||||
{
|
||||
/* Return TRUE if ok */
|
||||
|
|
@ -3113,6 +3167,11 @@ BOOL u_process_instance(char *nline)
|
|||
}
|
||||
}
|
||||
|
||||
/* NOTE
|
||||
The input line is expected to be a card in the deck which contains
|
||||
a Pspice .model timing model statement with all the '+' continuations
|
||||
added minus the '+'.
|
||||
*/
|
||||
BOOL u_process_model_line(char *line)
|
||||
{
|
||||
/* Translate a .model line to find the delays */
|
||||
|
|
|
|||
Loading…
Reference in New Issue