added symbol attributes @spice_get_current_<param>, @spice_get_modelparam_<param>, @spice_get_modelvoltage_<param>

This commit is contained in:
stefan schippers 2025-01-16 02:52:52 +01:00
parent f79f9ecf1d
commit 315c5bd600
2 changed files with 136 additions and 76 deletions

View File

@ -619,6 +619,29 @@ verilog_format="xnor #(@risedel , @falldel ) @name ( @@Z , @@A , @@B );"
sequence number <kbd>n</kbd>, extracted from simulation raw file (operating point or
cursor <kbd>b</kbd> position)</p>
<li><kbd>@spice_get_voltage</kbd></li>
<p> This attribute will be replaced by the voltage of the net attached to the first pin (pin number 0)
of the symbol </p>
<li><kbd>@spice_get_current</kbd></li>
<p> 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 <kbd>@spice_get_current</kbd> will display the
drain current of a mosfet if this attribute is placed inside a MOS symbol.</p>
<li><kbd>@spice_get_current_param</kbd></li>
<p> This will specify in <kbd>param</kbd> the current to display, for example: <br>
<kbd>@spice_get_current_ibs</kbd> to get the body-source current in a Mosfet,
<kbd>@spice_get_current_ie</kbd> to get the emitter current in a Bjt.</p>
<li><kbd>@spice_get_modelvoltage_param</kbd></li>
<p> This will specify in <kbd>param</kbd> the voltage to display, for example: <br>
<kbd>@spice_get_modelvoltage_vth</kbd> to get the Vth in a Mosfet</p>
<li><kbd>@spice_get_modelparam_param</kbd></li>
<p> This will specify in <kbd>param</kbd> the model parameter to display, for example: <br>
<kbd>@spice_get_modelparam_gm</kbd> to get the transconductance in a Mosfet</p>
<li><kbd>@spice_get_node spice_node </kbd></li>
<p>
<kbd>spice_node</kbd> Will be replaced with the Spice simulated value for that node.<br>

View File

@ -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<n>(...) */
/* @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_, &param);
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_, &param);
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_, &param);
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 : "<NULL>");
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_, &param);
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)
{