Add support for srff.
This commit is contained in:
parent
b64f684a62
commit
4c2152c74f
|
|
@ -51,7 +51,6 @@
|
||||||
#include "ngspice/stringskip.h"
|
#include "ngspice/stringskip.h"
|
||||||
#include "ngspice/stringutil.h"
|
#include "ngspice/stringutil.h"
|
||||||
#include "ngspice/inpdefs.h"
|
#include "ngspice/inpdefs.h"
|
||||||
#include "ngspice/cpextern.h"
|
|
||||||
#include "ngspice/macros.h"
|
#include "ngspice/macros.h"
|
||||||
#include "ngspice/udevices.h"
|
#include "ngspice/udevices.h"
|
||||||
|
|
||||||
|
|
@ -135,6 +134,19 @@ struct jkff_instance {
|
||||||
char *tmodel;
|
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 dltch_instance {
|
||||||
struct instance_hdr *hdrp;
|
struct instance_hdr *hdrp;
|
||||||
char *prebar;
|
char *prebar;
|
||||||
|
|
@ -292,9 +304,7 @@ static char *find_xspice_for_delay(char *itype)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 's': {
|
case 's': {
|
||||||
/* Not implemented
|
|
||||||
if (eq(itype, "srff")) { return xspice_tab[D_SRFF]; }
|
if (eq(itype, "srff")) { return xspice_tab[D_SRFF]; }
|
||||||
*/
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'x': {
|
case 'x': {
|
||||||
|
|
@ -574,6 +584,10 @@ static Xlatep find_tmodel_in_xlator(Xlatep x, Xlatorp xlp)
|
||||||
if (eq(x1->xspice, x->xspice)) {
|
if (eq(x1->xspice, x->xspice)) {
|
||||||
return x1;
|
return x1;
|
||||||
}
|
}
|
||||||
|
if (xlp == default_models && eq(x->utype, "ugff") &&
|
||||||
|
eq(x->tmodel, "d0_gff")) {
|
||||||
|
return x1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
@ -788,7 +802,7 @@ static void delete_instance_hdr(struct instance_hdr *hdr)
|
||||||
|
|
||||||
/* NOTE
|
/* NOTE
|
||||||
There are translate_...() functions for each instance type (gates, arrays
|
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
|
For each type (except pullup/down) an instance struct is created by calling
|
||||||
the corresponding create_..._instance() then add_..._inout_timing_model()
|
the corresponding create_..._instance() then add_..._inout_timing_model()
|
||||||
functions. The instance struct returned by 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;
|
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)
|
static struct gate_instance *create_gate_instance(struct instance_hdr *hdrp)
|
||||||
{
|
{
|
||||||
struct gate_instance *gip;
|
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);
|
instance_name = tprintf("a%s_%d", iname, i);
|
||||||
if (eq(qout, "$d_nc")) {
|
if (eq(qout, "$d_nc")) {
|
||||||
/* NULL not allowed??? */
|
/* 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);
|
instance_name, darr[i], gate, preb, clrb, iname, i);
|
||||||
} else {
|
} else {
|
||||||
s1 = tprintf("%s %s %s %s %s %s",
|
s1 = tprintf("%s %s %s %s %s %s",
|
||||||
|
|
@ -1359,7 +1436,7 @@ static Xlatorp gen_dltch_instance(struct dltch_instance *ip)
|
||||||
qbout = qbarr[i];
|
qbout = qbarr[i];
|
||||||
if (eq(qbout, "$d_nc")) {
|
if (eq(qbout, "$d_nc")) {
|
||||||
/* NULL not allowed??? */
|
/* NULL not allowed??? */
|
||||||
s2 = tprintf(" ncn%s_%d %s", iname, i, modelnm);
|
s2 = tprintf(" ncn_%s_%d %s", iname, i, modelnm);
|
||||||
} else {
|
} else {
|
||||||
s2 = tprintf(" %s %s", qbout, modelnm);
|
s2 = tprintf(" %s %s", qbout, modelnm);
|
||||||
}
|
}
|
||||||
|
|
@ -1385,6 +1462,86 @@ static Xlatorp gen_dltch_instance(struct dltch_instance *ip)
|
||||||
return xxp;
|
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)
|
static Xlatorp gen_compound_instance(struct compound_instance *compi)
|
||||||
{
|
{
|
||||||
char **inarr, *itype, *output, *tmodel;
|
char **inarr, *itype, *output, *tmodel;
|
||||||
|
|
@ -2337,6 +2494,10 @@ static struct dltch_instance *add_dltch_inout_timing_model(
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (strncmp(dlp->gate, "$d_", 3) == 0) {
|
||||||
|
tfree(dlp);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
if (eq(dlp->prebar, "$d_lo") || eq(dlp->prebar, "$d_nc")) {
|
if (eq(dlp->prebar, "$d_lo") || eq(dlp->prebar, "$d_nc")) {
|
||||||
tfree(dlp);
|
tfree(dlp);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
@ -2433,6 +2594,99 @@ static struct jkff_instance *add_jkff_inout_timing_model(
|
||||||
return jkffip;
|
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(
|
static struct compound_instance *add_compound_inout_timing_model(
|
||||||
struct instance_hdr *hdr, char *start)
|
struct instance_hdr *hdr, char *start)
|
||||||
{
|
{
|
||||||
|
|
@ -2702,6 +2956,7 @@ static Xlatorp translate_ff_latch(struct instance_hdr *hdr, char *start)
|
||||||
char *itype;
|
char *itype;
|
||||||
struct dff_instance *dffp = NULL;
|
struct dff_instance *dffp = NULL;
|
||||||
struct jkff_instance *jkffp = NULL;
|
struct jkff_instance *jkffp = NULL;
|
||||||
|
struct srff_instance *srffp = NULL;
|
||||||
struct dltch_instance *dltchp = NULL;
|
struct dltch_instance *dltchp = NULL;
|
||||||
Xlatorp xp;
|
Xlatorp xp;
|
||||||
|
|
||||||
|
|
@ -2720,6 +2975,13 @@ static Xlatorp translate_ff_latch(struct instance_hdr *hdr, char *start)
|
||||||
delete_jkff_instance(jkffp);
|
delete_jkff_instance(jkffp);
|
||||||
return xp;
|
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")) {
|
} else if (eq(itype, "dltch")) {
|
||||||
dltchp = add_dltch_inout_timing_model(hdr, start);
|
dltchp = add_dltch_inout_timing_model(hdr, start);
|
||||||
if (dltchp) {
|
if (dltchp) {
|
||||||
|
|
@ -2815,7 +3077,8 @@ BOOL u_process_instance(char *nline)
|
||||||
xp = translate_gate(hdr, p1);
|
xp = translate_gate(hdr, p1);
|
||||||
} else if (is_compound_gate(itype)) {
|
} else if (is_compound_gate(itype)) {
|
||||||
xp = translate_gate(hdr, p1);
|
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);
|
xp = translate_ff_latch(hdr, p1);
|
||||||
} else if (eq(itype, "pullup") || eq(itype, "pulldn")) {
|
} else if (eq(itype, "pullup") || eq(itype, "pulldn")) {
|
||||||
xp = translate_pull(hdr, p1);
|
xp = translate_pull(hdr, p1);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue