Add support for srff.

This commit is contained in:
Brian Taylor 2022-06-05 12:29:02 -07:00 committed by Holger Vogt
parent b64f684a62
commit 4c2152c74f
1 changed files with 270 additions and 7 deletions

View File

@ -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);