From c8db059144358c3da78d4dbfe63cfed3303ef8f2 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Sat, 1 May 2021 14:55:23 +0200 Subject: [PATCH] Use 'm' and 'multi' correctly in PDKs If there is alraedy m=xx in a subcircuit instance line, replace it by m='m*xx' to aknowledge the additional m. Tested with an (old) TSMC PDK and with Skywater PDK. --- src/frontend/inpcom.c | 43 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 40 insertions(+), 3 deletions(-) diff --git a/src/frontend/inpcom.c b/src/frontend/inpcom.c index 21322aed9..2948dc712 100644 --- a/src/frontend/inpcom.c +++ b/src/frontend/inpcom.c @@ -869,13 +869,13 @@ struct card *inp_readall(FILE *fp, const char *dir_name, inp_fix_param_values(working); inp_reorder_params(subckt_w_params, cc); - +// tprint(working); /* Special handling for large PDKs: We need to know W and L of transistor subcircuits by checking their x invocation */ inp_get_w_l_x(working); inp_fix_inst_calls_for_numparam(subckt_w_params, working); -// tprint(working); + delete_names(subckt_w_params); subckt_w_params = NULL; if (!cp_getvar("no_auto_gnd", CP_BOOL, NULL, 0)) @@ -3312,7 +3312,36 @@ static int inp_fix_subckt_multiplier(struct names *subckt_w_params, /* no 'm' for model cards */ if (ciprefix(".model", curr_line)) continue; - new_str = tprintf("%s m={m}", curr_line); + if (newcompat.hs) { + /* if there is already an m=xx in the instance line, multiply it with the new m */ + char* mult = strstr(curr_line, " m="); + if (mult) { + char* beg = copy_substring(curr_line, mult); + mult = mult + 3; + char* multval = gettok(&mult); + /* replace { } or ' ' by ( ) to avoid double braces */ + if (*multval == '{' || *multval == '\'') { + *multval = '('; + } + char* tmpstr = strchr(multval, '}'); + if (tmpstr) { + *tmpstr = ')'; + } + tmpstr = strchr(multval, '\''); + if (tmpstr) { + *tmpstr = ')'; + } + new_str = tprintf("%s m={m*%s} %s", beg, multval, mult); + tfree(beg); + tfree(multval); + } + else { + new_str = tprintf("%s m={m}", curr_line); + } + } + else { + new_str = tprintf("%s m={m}", curr_line); + } tfree(card->line); card->line = new_str; @@ -8910,6 +8939,7 @@ static void inp_check_syntax(struct card *deck) { struct card *card; int check_control = 0, check_subs = 0, check_if = 0, check_ch = 0; + bool mwarn = FALSE; /* will lead to crash in inp.c, fcn inp_spsource */ if (ciprefix(".param", deck->line) || ciprefix(".meas", deck->line)) { @@ -8953,6 +8983,13 @@ static void inp_check_syntax(struct card *deck) } // check for .subckt ... .ends else if (ciprefix(".subckt", cut_line)) { + // warn if m=xx on .subckt line + if (newcompat.hs && !mwarn) { + if (strstr(cut_line, " m=") || strstr(cut_line, " m =")) { + fprintf(stderr, "Warning: m=xx on .subckt line will override multiplier m hierarchy!\n\n"); + mwarn = TRUE; + } + } // nesting may be critical if params are involved if (check_subs > 0 && strchr(cut_line, '=')) fprintf(cp_err,