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)
{