Add support for srff.
This commit is contained in:
parent
b64f684a62
commit
4c2152c74f
|
|
@ -51,7 +51,6 @@
|
|||
#include "ngspice/stringskip.h"
|
||||
#include "ngspice/stringutil.h"
|
||||
#include "ngspice/inpdefs.h"
|
||||
#include "ngspice/cpextern.h"
|
||||
#include "ngspice/macros.h"
|
||||
#include "ngspice/udevices.h"
|
||||
|
||||
|
|
@ -135,6 +134,19 @@ struct jkff_instance {
|
|||
char *tmodel;
|
||||
};
|
||||
|
||||
struct srff_instance {
|
||||
struct instance_hdr *hdrp;
|
||||
char *prebar;
|
||||
char *clrbar;
|
||||
char *gate;
|
||||
int num_gates;
|
||||
char **s_in;
|
||||
char **r_in;
|
||||
char **q_out;
|
||||
char **qb_out;
|
||||
char *tmodel;
|
||||
};
|
||||
|
||||
struct dltch_instance {
|
||||
struct instance_hdr *hdrp;
|
||||
char *prebar;
|
||||
|
|
@ -292,9 +304,7 @@ static char *find_xspice_for_delay(char *itype)
|
|||
break;
|
||||
}
|
||||
case 's': {
|
||||
/* Not implemented
|
||||
if (eq(itype, "srff")) { return xspice_tab[D_SRFF]; }
|
||||
*/
|
||||
break;
|
||||
}
|
||||
case 'x': {
|
||||
|
|
@ -574,6 +584,10 @@ static Xlatep find_tmodel_in_xlator(Xlatep x, Xlatorp xlp)
|
|||
if (eq(x1->xspice, x->xspice)) {
|
||||
return x1;
|
||||
}
|
||||
if (xlp == default_models && eq(x->utype, "ugff") &&
|
||||
eq(x->tmodel, "d0_gff")) {
|
||||
return x1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
|
|
@ -788,7 +802,7 @@ static void delete_instance_hdr(struct instance_hdr *hdr)
|
|||
|
||||
/* NOTE
|
||||
There are translate_...() functions for each instance type (gates, arrays
|
||||
of gates, compound gates, dff, jkff, dltch).
|
||||
of gates, compound gates, dff, jkff, dltch, srff).
|
||||
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()
|
||||
|
|
@ -969,6 +983,69 @@ static void delete_jkff_instance(struct jkff_instance *jkp)
|
|||
return;
|
||||
}
|
||||
|
||||
static struct srff_instance *create_srff_instance(struct instance_hdr *hdrp)
|
||||
{
|
||||
struct srff_instance *srffp;
|
||||
|
||||
srffp = TMALLOC(struct srff_instance, 1);
|
||||
srffp->hdrp = hdrp;
|
||||
srffp->prebar = NULL;
|
||||
srffp->clrbar = NULL;
|
||||
srffp->gate = NULL;
|
||||
srffp->num_gates = 0;
|
||||
srffp->s_in = NULL;
|
||||
srffp->r_in = NULL;
|
||||
srffp->q_out = NULL;
|
||||
srffp->qb_out = NULL;
|
||||
srffp->tmodel = NULL;
|
||||
return srffp;
|
||||
}
|
||||
|
||||
static void delete_srff_instance(struct srff_instance *srffp)
|
||||
{
|
||||
char **arr;
|
||||
int i;
|
||||
|
||||
if (!srffp) { return; }
|
||||
if (srffp->hdrp) { delete_instance_hdr(srffp->hdrp); }
|
||||
if (srffp->prebar) { tfree(srffp->prebar); }
|
||||
if (srffp->clrbar) { tfree(srffp->clrbar); }
|
||||
if (srffp->gate) { tfree(srffp->gate); }
|
||||
if (srffp->tmodel) { tfree(srffp->tmodel); }
|
||||
if (srffp->num_gates > 0) {
|
||||
if (srffp->s_in) {
|
||||
arr = srffp->s_in;
|
||||
for (i = 0; i < srffp->num_gates; i++) {
|
||||
tfree(arr[i]);
|
||||
}
|
||||
tfree(srffp->s_in);
|
||||
}
|
||||
if (srffp->r_in) {
|
||||
arr = srffp->r_in;
|
||||
for (i = 0; i < srffp->num_gates; i++) {
|
||||
tfree(arr[i]);
|
||||
}
|
||||
tfree(srffp->r_in);
|
||||
}
|
||||
if (srffp->q_out) {
|
||||
arr = srffp->q_out;
|
||||
for (i = 0; i < srffp->num_gates; i++) {
|
||||
tfree(arr[i]);
|
||||
}
|
||||
tfree(srffp->q_out);
|
||||
}
|
||||
if (srffp->qb_out) {
|
||||
arr = srffp->qb_out;
|
||||
for (i = 0; i < srffp->num_gates; i++) {
|
||||
tfree(arr[i]);
|
||||
}
|
||||
tfree(srffp->qb_out);
|
||||
}
|
||||
}
|
||||
tfree(srffp);
|
||||
return;
|
||||
}
|
||||
|
||||
static struct gate_instance *create_gate_instance(struct instance_hdr *hdrp)
|
||||
{
|
||||
struct gate_instance *gip;
|
||||
|
|
@ -1350,7 +1427,7 @@ static Xlatorp gen_dltch_instance(struct dltch_instance *ip)
|
|||
instance_name = tprintf("a%s_%d", iname, i);
|
||||
if (eq(qout, "$d_nc")) {
|
||||
/* NULL not allowed??? */
|
||||
s1 = tprintf("%s %s %s %s %s nco%s_%d",
|
||||
s1 = tprintf("%s %s %s %s %s nco_%s_%d",
|
||||
instance_name, darr[i], gate, preb, clrb, iname, i);
|
||||
} else {
|
||||
s1 = tprintf("%s %s %s %s %s %s",
|
||||
|
|
@ -1359,7 +1436,7 @@ static Xlatorp gen_dltch_instance(struct dltch_instance *ip)
|
|||
qbout = qbarr[i];
|
||||
if (eq(qbout, "$d_nc")) {
|
||||
/* NULL not allowed??? */
|
||||
s2 = tprintf(" ncn%s_%d %s", iname, i, modelnm);
|
||||
s2 = tprintf(" ncn_%s_%d %s", iname, i, modelnm);
|
||||
} else {
|
||||
s2 = tprintf(" %s %s", qbout, modelnm);
|
||||
}
|
||||
|
|
@ -1385,6 +1462,86 @@ static Xlatorp gen_dltch_instance(struct dltch_instance *ip)
|
|||
return xxp;
|
||||
}
|
||||
|
||||
static Xlatorp gen_srff_instance(struct srff_instance *srffp)
|
||||
{
|
||||
char *itype, *iname, **sarr, **rarr, **qarr, **qbarr;
|
||||
char *preb, *clrb, *gate, *tmodel, *qout, *qbout;
|
||||
int i, num_gates;
|
||||
char *modelnm, *s1, *s2, *s3;
|
||||
Xlatorp xxp = NULL;
|
||||
Xlatep xdata = NULL;
|
||||
BOOL need_preb_inv = FALSE, need_clrb_inv = FALSE;
|
||||
|
||||
if (!srffp) { return NULL; }
|
||||
itype = srffp->hdrp->instance_type;
|
||||
iname = srffp->hdrp->instance_name;
|
||||
num_gates = srffp->num_gates;
|
||||
sarr = srffp->s_in;
|
||||
rarr = srffp->r_in;
|
||||
qarr = srffp->q_out;
|
||||
qbarr = srffp->qb_out;
|
||||
preb = srffp->prebar;
|
||||
clrb = srffp->clrbar;
|
||||
|
||||
xxp = create_xlator();
|
||||
if (eq(preb, "$d_hi")) {
|
||||
preb = "NULL";
|
||||
} else {
|
||||
need_preb_inv = TRUE;
|
||||
preb = new_inverter(iname, preb, xxp);
|
||||
}
|
||||
|
||||
if (eq(clrb, "$d_hi")) {
|
||||
clrb = "NULL";
|
||||
} else {
|
||||
need_clrb_inv = TRUE;
|
||||
clrb = new_inverter(iname, clrb, xxp);
|
||||
}
|
||||
gate = srffp->gate;
|
||||
tmodel = srffp->tmodel;
|
||||
/* model name, same for each latch */
|
||||
modelnm = tprintf("d_a%s_%s", iname, itype);
|
||||
for (i = 0; i < num_gates; i++) {
|
||||
char *instance_name = NULL;
|
||||
qout = qarr[i];
|
||||
instance_name = tprintf("a%s_%d", iname, i);
|
||||
if (eq(qout, "$d_nc")) {
|
||||
/* NULL not allowed??? */
|
||||
s1 = tprintf("%s %s %s %s %s %s nco_%s_%d",
|
||||
instance_name, sarr[i], rarr[i], gate, preb, clrb, iname, i);
|
||||
} else {
|
||||
s1 = tprintf("%s %s %s %s %s %s %s",
|
||||
instance_name, sarr[i], rarr[i], gate, preb, clrb, qout);
|
||||
}
|
||||
qbout = qbarr[i];
|
||||
if (eq(qbout, "$d_nc")) {
|
||||
/* NULL not allowed??? */
|
||||
s2 = tprintf(" ncn_%s_%d %s", iname, i, modelnm);
|
||||
} else {
|
||||
s2 = tprintf(" %s %s", qbout, modelnm);
|
||||
}
|
||||
s3 = tprintf("%s%s", s1, s2);
|
||||
xdata = create_xlate_instance(s3, " d_srlatch", tmodel, modelnm);
|
||||
xxp = add_xlator(xxp, xdata);
|
||||
tfree(s1);
|
||||
tfree(s2);
|
||||
tfree(s3);
|
||||
tfree(instance_name);
|
||||
}
|
||||
if (!gen_timing_model(tmodel, "ugff", "d_srlatch", modelnm, xxp)) {
|
||||
printf("WARNING unable to find tmodel %s for %s d_srlatch\n",
|
||||
tmodel, modelnm);
|
||||
}
|
||||
if (need_preb_inv || need_clrb_inv) {
|
||||
add_zero_delay_inverter_model = TRUE;
|
||||
}
|
||||
if (need_preb_inv) { tfree(preb); }
|
||||
if (need_clrb_inv) { tfree(clrb); }
|
||||
tfree(modelnm);
|
||||
|
||||
return xxp;
|
||||
}
|
||||
|
||||
static Xlatorp gen_compound_instance(struct compound_instance *compi)
|
||||
{
|
||||
char **inarr, *itype, *output, *tmodel;
|
||||
|
|
@ -2337,6 +2494,10 @@ static struct dltch_instance *add_dltch_inout_timing_model(
|
|||
return NULL;
|
||||
}
|
||||
}
|
||||
if (strncmp(dlp->gate, "$d_", 3) == 0) {
|
||||
tfree(dlp);
|
||||
return NULL;
|
||||
}
|
||||
if (eq(dlp->prebar, "$d_lo") || eq(dlp->prebar, "$d_nc")) {
|
||||
tfree(dlp);
|
||||
return NULL;
|
||||
|
|
@ -2433,6 +2594,99 @@ static struct jkff_instance *add_jkff_inout_timing_model(
|
|||
return jkffip;
|
||||
}
|
||||
|
||||
static struct srff_instance *add_srff_inout_timing_model(
|
||||
struct instance_hdr *hdr, char *start)
|
||||
{
|
||||
char *tok, *copyline;
|
||||
char *name, **arrp, **arrpr;
|
||||
int i, num_gates = hdr->num1;
|
||||
struct srff_instance *srffp = NULL;
|
||||
|
||||
srffp = create_srff_instance(hdr);
|
||||
srffp->num_gates = num_gates;
|
||||
copyline = TMALLOC(char, strlen(start) + 1);
|
||||
(void) memcpy(copyline, start, strlen(start) + 1);
|
||||
|
||||
/* prebar, clrbar, gate */
|
||||
tok = strtok(copyline, " \t");
|
||||
srffp->prebar = TMALLOC(char, strlen(tok) + 1);
|
||||
(void) memcpy(srffp->prebar, tok, strlen(tok) + 1);
|
||||
|
||||
tok = strtok(NULL, " \t");
|
||||
srffp->clrbar = TMALLOC(char, strlen(tok) + 1);
|
||||
(void) memcpy(srffp->clrbar, tok, strlen(tok) + 1);
|
||||
|
||||
tok = strtok(NULL, " \t");
|
||||
srffp->gate = TMALLOC(char, strlen(tok) + 1);
|
||||
(void) memcpy(srffp->gate, tok, strlen(tok) + 1);
|
||||
|
||||
/* s inputs */
|
||||
srffp->s_in = TMALLOC(char *, num_gates);
|
||||
arrp = srffp->s_in;
|
||||
for (i = 0; i < num_gates; i++) {
|
||||
tok = strtok(NULL, " \t");
|
||||
name = TMALLOC(char, strlen(tok) + 1);
|
||||
(void) memcpy(name, tok, strlen(tok) + 1);
|
||||
arrp[i] = name;
|
||||
}
|
||||
/* r inputs */
|
||||
srffp->r_in = TMALLOC(char *, num_gates);
|
||||
arrp = srffp->r_in;
|
||||
for (i = 0; i < num_gates; i++) {
|
||||
tok = strtok(NULL, " \t");
|
||||
name = TMALLOC(char, strlen(tok) + 1);
|
||||
(void) memcpy(name, tok, strlen(tok) + 1);
|
||||
arrp[i] = name;
|
||||
}
|
||||
/* q_out outputs */
|
||||
srffp->q_out = TMALLOC(char *, num_gates);
|
||||
arrp = srffp->q_out;
|
||||
for (i = 0; i < num_gates; i++) {
|
||||
tok = strtok(NULL, " \t");
|
||||
name = TMALLOC(char, strlen(tok) + 1);
|
||||
(void) memcpy(name, tok, strlen(tok) + 1);
|
||||
arrp[i] = name;
|
||||
}
|
||||
/* qb_out outputs */
|
||||
srffp->qb_out = TMALLOC(char *, num_gates);
|
||||
arrp = srffp->qb_out;
|
||||
for (i = 0; i < num_gates; i++) {
|
||||
tok = strtok(NULL, " \t");
|
||||
name = TMALLOC(char, strlen(tok) + 1);
|
||||
(void) memcpy(name, tok, strlen(tok) + 1);
|
||||
arrp[i] = name;
|
||||
}
|
||||
/* timing model */
|
||||
tok = strtok(NULL, " \t");
|
||||
srffp->tmodel = TMALLOC(char, strlen(tok) + 1);
|
||||
(void) memcpy(srffp->tmodel, tok, strlen(tok) + 1);
|
||||
tfree(copyline);
|
||||
|
||||
/* Reject incompatible inputs */
|
||||
arrp = srffp->s_in;
|
||||
arrpr = srffp->r_in;
|
||||
for (i = 0; i < num_gates; i++) {
|
||||
if (strncmp(arrp[i], "$d_", 3) == 0 ||
|
||||
strncmp(arrpr[i], "$d_", 3) == 0) {
|
||||
tfree(srffp);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if (strncmp(srffp->gate, "$d_", 3) == 0) {
|
||||
tfree(srffp);
|
||||
return NULL;
|
||||
}
|
||||
if (eq(srffp->prebar, "$d_lo") || eq(srffp->prebar, "$d_nc")) {
|
||||
tfree(srffp);
|
||||
return NULL;
|
||||
}
|
||||
if (eq(srffp->clrbar, "$d_lo") || eq(srffp->clrbar, "$d_nc")) {
|
||||
tfree(srffp);
|
||||
return NULL;
|
||||
}
|
||||
return srffp;
|
||||
}
|
||||
|
||||
static struct compound_instance *add_compound_inout_timing_model(
|
||||
struct instance_hdr *hdr, char *start)
|
||||
{
|
||||
|
|
@ -2702,6 +2956,7 @@ static Xlatorp translate_ff_latch(struct instance_hdr *hdr, char *start)
|
|||
char *itype;
|
||||
struct dff_instance *dffp = NULL;
|
||||
struct jkff_instance *jkffp = NULL;
|
||||
struct srff_instance *srffp = NULL;
|
||||
struct dltch_instance *dltchp = NULL;
|
||||
Xlatorp xp;
|
||||
|
||||
|
|
@ -2720,6 +2975,13 @@ static Xlatorp translate_ff_latch(struct instance_hdr *hdr, char *start)
|
|||
delete_jkff_instance(jkffp);
|
||||
return xp;
|
||||
}
|
||||
} else if (eq(itype, "srff")) {
|
||||
srffp = add_srff_inout_timing_model(hdr, start);
|
||||
if (srffp) {
|
||||
xp = gen_srff_instance(srffp);
|
||||
delete_srff_instance(srffp);
|
||||
return xp;
|
||||
}
|
||||
} else if (eq(itype, "dltch")) {
|
||||
dltchp = add_dltch_inout_timing_model(hdr, start);
|
||||
if (dltchp) {
|
||||
|
|
@ -2815,7 +3077,8 @@ BOOL u_process_instance(char *nline)
|
|||
xp = translate_gate(hdr, p1);
|
||||
} else if (is_compound_gate(itype)) {
|
||||
xp = translate_gate(hdr, p1);
|
||||
} else if (eq(itype, "dff") || eq(itype, "jkff") || eq(itype, "dltch")) {
|
||||
} else if (eq(itype, "dff") || eq(itype, "jkff") ||
|
||||
eq(itype, "dltch") || eq(itype, "srff")) {
|
||||
xp = translate_ff_latch(hdr, p1);
|
||||
} else if (eq(itype, "pullup") || eq(itype, "pulldn")) {
|
||||
xp = translate_pull(hdr, p1);
|
||||
|
|
|
|||
Loading…
Reference in New Issue