diff --git a/doc/xschem_man/symbol_property_syntax.html b/doc/xschem_man/symbol_property_syntax.html index d0ca082c..9aa02448 100644 --- a/doc/xschem_man/symbol_property_syntax.html +++ b/doc/xschem_man/symbol_property_syntax.html @@ -619,6 +619,29 @@ verilog_format="xnor #(@risedel , @falldel ) @name ( @@Z , @@A , @@B );" sequence number n, extracted from simulation raw file (operating point or cursor b position)

+
  • @spice_get_voltage
  • +

    This attribute will be replaced by the voltage of the net attached to the first pin (pin number 0) + of the symbol

    + +
  • @spice_get_current
  • +

    This attribute will be replaced by the current through the first pin of the primitive symbol + according to the SPICE syntax. This can be used for elementary devices like voltage sources, + resistors, mosfets, bjts and so on. For example @spice_get_current will display the + drain current of a mosfet if this attribute is placed inside a MOS symbol.

    + +
  • @spice_get_current_param
  • +

    This will specify in param the current to display, for example:
    + @spice_get_current_ibs to get the body-source current in a Mosfet, + @spice_get_current_ie to get the emitter current in a Bjt.

    + +
  • @spice_get_modelvoltage_param
  • +

    This will specify in param the voltage to display, for example:
    + @spice_get_modelvoltage_vth to get the Vth in a Mosfet

    + +
  • @spice_get_modelparam_param
  • +

    This will specify in param the model parameter to display, for example:
    + @spice_get_modelparam_gm to get the transconductance in a Mosfet

    +
  • @spice_get_node spice_node
  • spice_node Will be replaced with the Spice simulated value for that node.
    diff --git a/src/token.c b/src/token.c index d70a6ad4..8745aaf6 100644 --- a/src/token.c +++ b/src/token.c @@ -3749,7 +3749,11 @@ const char *translate(int inst, const char* s) if(!get_sp_cur) { get_sp_cur = my_malloc(_ALLOC_ID_, sizeof(regex_t)); - regcomp(get_sp_cur, "^@spice_get_current[0-9]*\\(", REG_NOSUB | REG_EXTENDED); + /* @spice_get_current_param(...) or @spice_get_modelparam_param(...) */ + /* @spice_get_current(...) or @spice_get_modelparam(...) */ + /* @spice_get_modelvoltage(...) or @spice_get_modelvoltage_param(...) */ + regcomp(get_sp_cur, + "^@spice_get_(current|modelparam|modelvoltage)(_[a-zA-Z][a-zA-Z0-9_]*)*\\(", REG_NOSUB | REG_EXTENDED); } sp_prefix = tclgetboolvar("spiceprefix"); @@ -4082,7 +4086,12 @@ const char *translate(int inst, const char* s) } } } - /* @spice_get_current(...) or @spice_get_current(...) */ + /* @spice_get_current(...) or @spice_get_current_param(...) + * @spice_get_modelparam(...) or @spice_get_modelparam_param(...) + * @spice_get_modelvoltage(...) or @spice_get_modelvoltage_param(...) + * + * Only @spice_get_current(...) and @spice_get_current_param(...) are processed + * the other types are ignored */ else if(!regexec(get_sp_cur, token, 0 , NULL, 0) ) { int start_level; /* hierarchy level where waves were loaded */ @@ -4090,10 +4099,9 @@ const char *translate(int inst, const char* s) if(live && (start_level = sch_waves_loaded()) >= 0 && xctx->raw->annot_p>=0) { char *fqdev = NULL; const char *path = xctx->sch_path[xctx->currsch] + 1; - char *dev = NULL; - int ncurrent = 1; + char *dev = NULL, *param = NULL; size_t len; - int idx, n; + int idx, n = 0; double val = 0.0; const char *valstr; tmp = strlen(token) + 1; @@ -4109,8 +4117,12 @@ const char *translate(int inst, const char* s) if(!strncmp(token, "@spice_get_current(", 19)) { n = sscanf(token + 19, "%[^)]", dev); } else { - n = sscanf(token, "@spice_get_current%d(%[^)]", &ncurrent, dev); - dbg(1, "ncurrent=%d, dev=%s\n", ncurrent, dev); + param = my_malloc(_ALLOC_ID_, tmp); + n = sscanf(token, "@spice_get_current_%s(%[^)]", param, dev); + if(n < 2) { + my_free(_ALLOC_ID_, ¶m); + n = sscanf(token, "@spice_get_current[^(](%[^)]", dev); + } } if(n >= 1) { strtolower(dev); @@ -4128,11 +4140,9 @@ const char *translate(int inst, const char* s) if(vsource) { my_snprintf(fqdev, len, "i(%c.%s%s.%s)", prefix, path, instname, dev); } else if(prefix == 'q') { - const char *current[] = {"ic", "ic", "ib", "ie"}; - my_snprintf(fqdev, len, "i(@%c.%s%s.%s[%s])", prefix, path, instname, dev, current[ncurrent]); + my_snprintf(fqdev, len, "i(@%c.%s%s.%s[%s])", prefix, path, instname, dev, param ? param : "ic"); } else if(prefix == 'd' || prefix == 'm') { - const char *current[] = {"id", "id", "ig", "is", "ib"}; - my_snprintf(fqdev, len, "i(@%c.%s%s.%s[%s])", prefix, path, instname, dev, current[ncurrent]); + my_snprintf(fqdev, len, "i(@%c.%s%s.%s[%s])", prefix, path, instname, dev, param ? param : "id"); } else if(prefix == 'i') { my_snprintf(fqdev, len, "i(@%c.%s%s.%s[current])", prefix, path, instname, dev); } else { @@ -4165,6 +4175,7 @@ const char *translate(int inst, const char* s) dbg(1, "instname %s, dev=%s, fqdev=%s idx=%d valstr=%s\n", instname, dev, fqdev, idx, valstr); my_free(_ALLOC_ID_, &fqdev); } /* if(n == 1) */ + if(param) my_free(_ALLOC_ID_, ¶m); my_free(_ALLOC_ID_, &dev); } /* if(path) */ } /* if((start_level = sch_waves_loaded()) >= 0 && xctx->raw->annot_p>=0) */ @@ -4235,17 +4246,22 @@ const char *translate(int inst, const char* s) } } } - else if(strncmp(token,"@spice_get_current", 18)==0 ) + else if( + strncmp(token,"@spice_get_current", 18)==0 || + strncmp(token,"@spice_get_modelparam", 21)==0 || + strncmp(token,"@spice_get_modelvoltage", 23)==0 + ) { int start_level; /* hierarchy level where waves were loaded */ int live = tclgetboolvar("live_cursor2_backannotate"); if(live && (start_level = sch_waves_loaded()) >= 0 && xctx->raw->annot_p>=0) { char *fqdev = NULL; const char *path = xctx->sch_path[xctx->currsch] + 1; - char *dev = NULL; - int ncurrent = 1; + char *dev = NULL, *param = NULL; + int modelparam = 0; /* 0: current, 1: modelparam, 2: modelvoltage */ size_t len; int idx; + int error = 0; double val = 0.0; const char *valstr; if(path) { @@ -4255,73 +4271,94 @@ const char *translate(int inst, const char* s) if(*path == '.') skip++; ++path; } - if(strcmp(token, "@spice_get_current")) { - if(sscanf(token, "@spice_get_current%d", &ncurrent) != 1) ncurrent = 1; + /* token contans _param after @spice_get_current or @spice_get_modelparam + * or @spice_get_modelvoltage */ + if(strcmp(token, "@spice_get_current") && + strcmp(token, "@spice_get_modelparam") && + strcmp(token, "@spice_get_modelvoltage")) { + int n = 0; + param = my_malloc(_ALLOC_ID_, strlen(token) + 1); + n = sscanf(token, "@spice_get_current_%s", param); + if(n == 0) { + n = sscanf(token, "@spice_get_modelparam_%s", param); + modelparam = 1; + } + if(n == 0) { + n = sscanf(token, "@spice_get_modelvoltage_%s", param); + modelparam = 2; + } + if(n == 0) { + my_free(_ALLOC_ID_, ¶m); + error = 1; + } } - my_strdup2(_ALLOC_ID_, &dev, instname); - strtolower(dev); - len = strlen(path) + strlen(dev) + 21; /* some extra chars for i(..) wrapper */ - dbg(1, "dev=%s\n", dev); - fqdev = my_malloc(_ALLOC_ID_, len); - if(!sim_is_xyce) { - int prefix=dev[0]; - int vsource = (prefix == 'v') || (prefix == 'e'); - if(path[0]) { - if(vsource) { - my_snprintf(fqdev, len, "i(%c.%s%s)", prefix, path, dev); - } else if(prefix=='q') { - const char *current[] = {"ic", "ic", "ib", "ie"}; - my_snprintf(fqdev, len, "i(@%c.%s%s[%s])", prefix, path, dev, current[ncurrent]); - } else if(prefix=='d' || prefix == 'm') { - const char *current[] = {"id", "id", "ig", "is", "ib"}; - my_snprintf(fqdev, len, "i(@%c.%s%s[%s])", prefix, path, dev, current[ncurrent]); - } else if(prefix=='i') { - my_snprintf(fqdev, len, "i(@%c.%s%s[current])", prefix, path, dev); + if(!error) { + char *iprefix = modelparam == 0 ? "i(" : modelparam == 1 ? "" : "v("; + char *ipostfix = modelparam == 1 ? "" : ")"; + my_strdup2(_ALLOC_ID_, &dev, instname); + strtolower(dev); + len = strlen(path) + strlen(dev) + 21; /* some extra chars for i(..) wrapper */ + dbg(1, "token=%s, dev=%s param=%s\n", token, dev, param ? param : ""); + fqdev = my_malloc(_ALLOC_ID_, len); + if(!sim_is_xyce) { + int prefix=dev[0]; + int vsource = (prefix == 'v') || (prefix == 'e'); + if(path[0]) { + if(vsource) { + my_snprintf(fqdev, len, "i(%c.%s%s)", prefix, path, dev); + } else if(prefix=='q') { + my_snprintf(fqdev, len, "%s@%c.%s%s[%s]%s", + iprefix, prefix, path, dev, param ? param : "ic", ipostfix); + } else if(prefix=='d' || prefix == 'm') { + my_snprintf(fqdev, len, "%s@%c.%s%s[%s]%s", + iprefix, prefix, path, dev, param ? param : "id", ipostfix); + } else if(prefix=='i') { + my_snprintf(fqdev, len, "i(@%c.%s%s[current])", prefix, path, dev); + } else { + my_snprintf(fqdev, len, "i(@%c.%s%s[i])", prefix, path, dev); + } } else { - my_snprintf(fqdev, len, "i(@%c.%s%s[i])", prefix, path, dev); + if(vsource) { + my_snprintf(fqdev, len, "i(%s)", dev); + } else if(prefix == 'q') { + my_snprintf(fqdev, len, "%s@%s[%s]%s", iprefix, dev, param ? param : "ic", ipostfix); + } else if(prefix == 'd' || prefix == 'm') { + my_snprintf(fqdev, len, "%s@%s[%s]%s", iprefix, dev, param ? param : "id", ipostfix); + } else if(prefix == 'i') { + my_snprintf(fqdev, len, "i(@%s[current])"); + } else { + my_snprintf(fqdev, len, "i(@%s[i])", dev); + } } } else { - if(vsource) { - my_snprintf(fqdev, len, "i(%s)", dev); - } else if(prefix == 'q') { - const char *current[] = {"ic", "ic", "ib", "ie"}; - my_snprintf(fqdev, len, "i(@%s[%s])", dev, current[ncurrent]); - } else if(prefix == 'd' || prefix == 'm') { - const char *current[] = {"id", "id", "ig", "is", "ib"}; - my_snprintf(fqdev, len, "i(@%s[%s])", dev, current[ncurrent]); - } else if(prefix == 'i') { - my_snprintf(fqdev, len, "i(@%s[current])"); - } else { - my_snprintf(fqdev, len, "i(@%s[i])", dev); - } + my_snprintf(fqdev, len, "i(%s%s)", path, dev); } - } else { - my_snprintf(fqdev, len, "i(%s%s)", path, dev); - } - dbg(1, "fqdev=%s\n", fqdev); - strtolower(fqdev); - idx = get_raw_index(fqdev, NULL); - if(idx >= 0) { - val = xctx->raw->cursor_b_val[idx]; - } - if(idx < 0) { - valstr = "-"; - xctx->tok_size = 1; - len = 1; - } else { - valstr = engineering ? dtoa_eng(val) : dtoa(val); - len = xctx->tok_size; - } - if(len) { - STR_ALLOC(&result, len + result_pos, &size); - memcpy(result+result_pos, valstr, len+1); - result_pos += len; - } - dbg(1, "instname %s, dev=%s, fqdev=%s idx=%d valstr=%s\n", instname, dev, fqdev, idx, valstr); - my_free(_ALLOC_ID_, &fqdev); - my_free(_ALLOC_ID_, &dev); - } - } + if(param) my_free(_ALLOC_ID_, ¶m); + dbg(1, "fqdev=%s\n", fqdev); + strtolower(fqdev); + idx = get_raw_index(fqdev, NULL); + if(idx >= 0) { + val = xctx->raw->cursor_b_val[idx]; + } + if(idx < 0) { + valstr = "-"; + xctx->tok_size = 1; + len = 1; + } else { + valstr = engineering ? dtoa_eng(val) : dtoa(val); + len = xctx->tok_size; + } + if(len) { + STR_ALLOC(&result, len + result_pos, &size); + memcpy(result+result_pos, valstr, len+1); + result_pos += len; + } + dbg(1, "instname %s, dev=%s, fqdev=%s idx=%d valstr=%s\n", instname, dev, fqdev, idx, valstr); + my_free(_ALLOC_ID_, &fqdev); + my_free(_ALLOC_ID_, &dev); + } /* if(!error) */ + } /* if(path) */ + } /* (live && (start_level = sch_waves_loaded()) >= 0 && xctx->raw->annot_p>=0) */ } else if(strcmp(token,"@schvhdlprop")==0 && xctx->schvhdlprop) {