svgdraw.c: avoid setting stroke-width to excessively small (invisible) values; print_spice_element(): in format string if @param is given and in instance atttributes param=value@tag do a round of resolution of @tag looking in instance attributes, then in parent symbol instance attributes (in case of per-instance implementation (schematic=... attr) and finally in parent symbol template string. Doc udpades
This commit is contained in:
parent
7a589ef4fb
commit
a176f99db5
|
|
@ -547,7 +547,6 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li><kbd> abort_operation</kbd></li><pre>
|
||||
|
|
@ -1393,6 +1392,11 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
|
|||
Translate string 'str' replacing @xxx tokens with values in instance 'n' attributes
|
||||
Example: xschem translate vref {the voltage is @value}
|
||||
the voltage is 1.8 </pre>
|
||||
<li><kbd> translate3 str s1 [s2]</kbd></li><pre>
|
||||
Translate string 'str' replacing @xxx tokens with values in string s1 or if
|
||||
not found in string s2
|
||||
Example: xschem translate3 {the voltage is @value} {name=x12} {name=x1 value=1.8}
|
||||
the voltage is 1.8 </pre>
|
||||
<li><kbd> trim_chars str sep</kbd></li><pre>
|
||||
Remove leading and trailing chars matching any character in 'sep' from str </pre>
|
||||
<li><kbd> trim_wires</kbd></li><pre>
|
||||
|
|
@ -1506,6 +1510,7 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</ul>
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 41 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 42 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 44 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 37 KiB |
|
|
@ -196,7 +196,66 @@ m1 y a VSSPIN VSSPIN yyn w=wn l=lln ad='wn *4.3u' as='wn *4.3u' pd='wn *2+8.6u'
|
|||
duplicate the subcircuit, since model names can not be set as parameters.
|
||||
</p>
|
||||
|
||||
|
||||
<h3> Another example of spice models given as parameters</h3>
|
||||
|
||||
<p> Consider the following symbol instance:</p>
|
||||
<img src="instance_based_implementation_08.png">
|
||||
<p> with the following symbol definition</p>
|
||||
<img src="instance_based_implementation_09.png">
|
||||
<p> And the following schematic definition. Note the <kbd>model</kbd> syntax for the p-channel transistor
|
||||
(the n-channel transistor has a similar <kbd>model=modn@modeltag</kbd> definition):</p>
|
||||
<img src="instance_based_implementation_10.png">
|
||||
<p> The following netlist will be produced</p>
|
||||
<pre class="code">
|
||||
...
|
||||
...
|
||||
x4 LDCP4_B LDCP vcc vss inv4 wn=8.4u lln=2.4u wp=20u lp=2.4u m=1
|
||||
...
|
||||
...
|
||||
* expanding symbol: inv4.sym # of pins=2
|
||||
** sym_path: /home/schippes/.xschem/xschem_library/test_parametric_model/inv4.sym
|
||||
** sch_path: /home/schippes/.xschem/xschem_library/test_parametric_model/inv4.sch
|
||||
.subckt inv4 y a VCCPIN VSSPIN wn=10u lln=1.2u wp=10u lp=1.2u
|
||||
*.opin y
|
||||
*.ipin a
|
||||
m2 y a VCCPIN VCCPIN modp18 w=wp l=lp ad='wp *4.6u' as='wp *4.6u' pd='wp *2+9.2u' ps='wp *2+9.2u' m=1
|
||||
m1 y a VSSPIN VSSPIN modn18 w=wn l=lln ad='wn *4.3u' as='wn *4.3u' pd='wn *2+8.6u' ps='wn *2+8.6u' m=1
|
||||
.ends
|
||||
...
|
||||
...
|
||||
</pre>
|
||||
<p> You see the <kbd>@modeltag</kbd> will be substituted looking first in the mos transistor attributes
|
||||
(but there is no definition there), then in the containing symbol attributes (and there is
|
||||
a <kbd>modeltag=18</kbd> definition).</p>
|
||||
<p> Now suppose you want to place another instance of <kbd>inv4.sym</kbd> but with a different modeltag:
|
||||
Since we know that spice does not allow model names to be passed as parameters we need to specialize the
|
||||
<kbd>inv4.sym</kbd> subcircuit to a new <kbd>inv_1.sym</kbd> subcircuit.
|
||||
Therefore we give the attribute <kbd>schematic=inv4_1.sch</kbd>
|
||||
to the second inv4 instance. We also set there a different modeltag: <kbd>modeltag=13</kbd></p>
|
||||
<img src="instance_based_implementation_11.png">
|
||||
<p> The netlist for this additional instance will be: </p>
|
||||
<pre class="code">
|
||||
...
|
||||
...
|
||||
x5 LDCP5_B LDCP vcc vss inv4_1 wn=8.4u lln=2.4u wp=20u lp=2.4u m=1
|
||||
...
|
||||
...
|
||||
* expanding symbol: inv4_1.sym # of pins=2
|
||||
** sym_path: /home/schippes/.xschem/xschem_library/test_parametric_model/inv4.sym
|
||||
** sch_path: /home/schippes/.xschem/xschem_library/test_parametric_model/inv4.sch
|
||||
.subckt inv4_1 y a VCCPIN VSSPIN wn=10u lln=1.2u wp=10u lp=1.2u
|
||||
*.opin y
|
||||
*.ipin a
|
||||
m2 y a VCCPIN VCCPIN modp13 w=wp l=lp ad='wp *4.6u' as='wp *4.6u' pd='wp *2+9.2u' ps='wp *2+9.2u' m=1
|
||||
m1 y a VSSPIN VSSPIN modn13 w=wn l=lln ad='wn *4.3u' as='wn *4.3u' pd='wn *2+8.6u' ps='wn *2+8.6u' m=1
|
||||
.ends
|
||||
...
|
||||
...
|
||||
</pre>
|
||||
<p> This way it is possible from a single symbol (<kbd>inv4.sym</kbd> in the example) to netlist multiple instances of it
|
||||
with different models, in the example using a <kbd>modeltag</kbd> variable.</p>
|
||||
|
||||
|
||||
<!-- end of slide -->
|
||||
<div class="filler"></div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1887,7 +1887,7 @@ void get_additional_symbols(int what)
|
|||
my_strdup2(_ALLOC_ID_, &sch, tcl_hook2(
|
||||
str_replace( get_tok_value(xctx->inst[i].prop_ptr,"schematic",2), "@symname",
|
||||
get_cell(xctx->inst[i].name, 0), '\\')));
|
||||
dbg(1, "get_additional_symbols(): sch=%s\n", sch);
|
||||
dbg(1, "get_additional_symbols(): inst=%d sch=%s\n",i, sch);
|
||||
if(sch[0] && stat(abs_sym_path(sch, ""), &buf)) {/* schematic does not exist */
|
||||
my_snprintf(symbol_base_sch, PATH_MAX, "%s.sch", get_cell(xctx->sym[xctx->inst[i].ptr].name, 9999));
|
||||
dbg(1, "get_additional_symbols(): schematic not existing\n");
|
||||
|
|
|
|||
|
|
@ -5265,6 +5265,27 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
|
|||
}
|
||||
}
|
||||
|
||||
/* translate3 str s1 [s2]
|
||||
* Translate string 'str' replacing @xxx tokens with values in string s1 or if
|
||||
* not found in string s2
|
||||
* Example: xschem translate3 {the voltage is @value} {name=x12} {name=x1 value=1.8}
|
||||
* the voltage is 1.8 */
|
||||
else if(!strcmp(argv[1], "translate3") )
|
||||
{
|
||||
char *s = NULL;
|
||||
if(!xctx) {Tcl_SetResult(interp, not_avail, TCL_STATIC); return TCL_ERROR;}
|
||||
if(argc > 5) my_strdup2(_ALLOC_ID_, &s, translate3(argv[2], argv[3], argv[4], argv[5]));
|
||||
if(argc > 4) my_strdup2(_ALLOC_ID_, &s, translate3(argv[2], argv[3], argv[4], NULL));
|
||||
else if(argc > 3) my_strdup2(_ALLOC_ID_, &s, translate3(argv[2], argv[3], NULL, NULL));
|
||||
else {
|
||||
Tcl_SetResult(interp, "xschem translate3: missing arguments", TCL_STATIC);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
Tcl_ResetResult(interp);
|
||||
Tcl_SetResult(interp, s, TCL_VOLATILE);
|
||||
my_free(_ALLOC_ID_, &s);
|
||||
}
|
||||
|
||||
/* trim_chars str sep
|
||||
* Remove leading and trailing chars matching any character in 'sep' from str */
|
||||
else if(!strcmp(argv[1], "trim_chars"))
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ static double svg_linew; /* current width of lines / rectangles */
|
|||
|
||||
static void svg_restore_lw(void)
|
||||
{
|
||||
svg_linew = xctx->lw*1.2;
|
||||
svg_linew = (xctx->lw <= 0.01 ? 0.2 : xctx->lw) * 1.2;
|
||||
}
|
||||
|
||||
static void svg_xdrawline(int layer, int bus, double x1, double y1, double x2, double y2, int dash)
|
||||
|
|
|
|||
136
src/token.c
136
src/token.c
|
|
@ -2154,35 +2154,17 @@ int print_spice_element(FILE *fd, int inst)
|
|||
my_strdup2(_ALLOC_ID_, &val, get_tok_value(xctx->inst[inst].prop_ptr, token+1, 0));
|
||||
tok_size = xctx->tok_size;
|
||||
value = val;
|
||||
if(!strcmp(token + 1, "model") && strchr(value, '@')) {
|
||||
value = translate(inst, val);
|
||||
if(strchr(value, '@')) {
|
||||
/* Symbol format string contains model=@modp,
|
||||
* instance attributes does not contain a modp=xxx,
|
||||
* look up modp in **parent** symbol template attribute */
|
||||
dbg(1, "model: instance=%s ,val=%s, tok=%s, value=%s template=%s\n",
|
||||
xctx->inst[inst].instname,
|
||||
val, token, value, xctx->hier_attr[xctx->currsch - 1].templ);
|
||||
if(value[0] == '\0') {
|
||||
value=get_tok_value(xctx->hier_attr[xctx->currsch - 1].prop_ptr, val+1, 0);
|
||||
}
|
||||
if(value[0] == '\0') {
|
||||
value=get_tok_value(xctx->hier_attr[xctx->currsch - 1].templ, val+1, 0);
|
||||
}
|
||||
}
|
||||
else if(val[0] == '@' && !strpbrk(value + 1, "@ ")) {
|
||||
/* value = translate(inst, val); */
|
||||
value = get_tok_value(xctx->inst[inst].prop_ptr, val + 1, 0);
|
||||
dbg(1, "val=%s, tok=%s, value=%s template=%s",
|
||||
val, token, value, xctx->hier_attr[xctx->currsch - 1].templ);
|
||||
if(value[0] == '\0') {
|
||||
value=get_tok_value(xctx->hier_attr[xctx->currsch - 1].prop_ptr, val+1, 0);
|
||||
}
|
||||
if(value[0] == '\0') {
|
||||
value=get_tok_value(xctx->hier_attr[xctx->currsch - 1].templ, val+1, 0);
|
||||
}
|
||||
* look up modp in **parent** instance prop_ptr and symbol template attribute */
|
||||
|
||||
value = translate3(val, xctx->inst[inst].prop_ptr,
|
||||
xctx->hier_attr[xctx->currsch - 1].prop_ptr,
|
||||
xctx->hier_attr[xctx->currsch - 1].templ);
|
||||
}
|
||||
tok_val_len = strlen(value);
|
||||
if(!strcmp(token, "@spiceprefix")) {
|
||||
if(!strcmp(token, "@spiceprefix") && value[0]) {
|
||||
my_realloc(_ALLOC_ID_, &spiceprefixtag, tok_val_len+22);
|
||||
my_snprintf(spiceprefixtag, tok_val_len+22, "**** spice_prefix %s\n", value);
|
||||
value = spiceprefixtag;
|
||||
|
|
@ -2197,18 +2179,8 @@ int print_spice_element(FILE *fd, int inst)
|
|||
token_exists = 0; /* processed later */
|
||||
value = NULL;
|
||||
}
|
||||
/*
|
||||
if (!strncmp(value,"tcleval(", 8)) {
|
||||
dbg(1, "print_spice_element(): value=%s\n", value);
|
||||
my_strdup2(_ALLOC_ID_, &translatedvalue, value);
|
||||
my_strdup2(_ALLOC_ID_, &translatedvalue, translate(inst, translatedvalue));
|
||||
value = translatedvalue;
|
||||
}
|
||||
*/
|
||||
}
|
||||
if(!token_exists && token[0] =='%') {
|
||||
|
||||
|
||||
/* result_pos += my_snprintf(result + result_pos, tmp, "%s", token + 1); */
|
||||
my_mstrcat(_ALLOC_ID_, &result, token + 1, NULL);
|
||||
/* fputs(token + 1, fd); */
|
||||
|
|
@ -4339,3 +4311,97 @@ const char *translate2(Lcc *lcc, int level, char* s)
|
|||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* substitute given tokens in a string with their corresponding values */
|
||||
/* ex.: name=@name w=@w l=@l ---> name=m112 w=3e-6 l=0.8e-6 */
|
||||
/* using s1, s2, s3 in turn to resolve @tokens */
|
||||
/* if no definition for @token is found return @token as is in s */
|
||||
/* if s==NULL return emty string */
|
||||
const char *translate3(const char *s, const char *s1, const char *s2, const char *s3)
|
||||
{
|
||||
static const char *empty="";
|
||||
static char *translated_tok = NULL;
|
||||
static char *result=NULL; /* safe to keep even with multiple schematics */
|
||||
register int c, state=TOK_BEGIN, space;
|
||||
char *token=NULL;
|
||||
size_t sizetok=0;
|
||||
size_t token_pos=0;
|
||||
const char *value;
|
||||
int escape=0;
|
||||
char *value1 = NULL;
|
||||
|
||||
|
||||
if(!s || !xctx) {
|
||||
my_free(_ALLOC_ID_, &result);
|
||||
my_free(_ALLOC_ID_, &translated_tok);
|
||||
return empty;
|
||||
}
|
||||
dbg(2, "translate3():\n s=%s\n s1=%s\n s2=%s\n s3=%s\n", s, s1, s2, s3);
|
||||
my_strdup2(_ALLOC_ID_, &result, "");
|
||||
|
||||
while(1) {
|
||||
c=*s++;
|
||||
if(c=='\\') {
|
||||
escape=1;
|
||||
c=*s++; /* do not remove: breaks translation of format strings in netlists (escaping %) */
|
||||
}
|
||||
else escape=0;
|
||||
space=SPACE(c);
|
||||
if( state==TOK_BEGIN && (c=='@' || c=='%' ) && !escape ) state=TOK_TOKEN; /* 20161210 escape */
|
||||
else if(state==TOK_TOKEN && token_pos > 1 &&
|
||||
(
|
||||
( (space || c == '%' || c == '@') && !escape ) ||
|
||||
( (!space && c != '%' && c != '@') && escape )
|
||||
)
|
||||
) state=TOK_SEP;
|
||||
|
||||
STR_ALLOC(&token, token_pos, &sizetok);
|
||||
if(state==TOK_TOKEN) token[token_pos++]=(char)c;
|
||||
else if(state==TOK_SEP) {
|
||||
token[token_pos]='\0';
|
||||
value = get_tok_value(s1, token+1, 0);
|
||||
if(!xctx->tok_size && s2) {
|
||||
value=get_tok_value(s2, token+1, 0);
|
||||
}
|
||||
if(!xctx->tok_size && s3) {
|
||||
value=get_tok_value(s3, token+1, 0);
|
||||
}
|
||||
if(!xctx->tok_size) { /* above lines did not find a value for token */
|
||||
/* no definition found -> keep token */
|
||||
my_strcat(_ALLOC_ID_, &result, token);
|
||||
} else {
|
||||
my_strdup2(_ALLOC_ID_, &value1, value);
|
||||
my_strcat(_ALLOC_ID_, &result, value1);
|
||||
my_free(_ALLOC_ID_, &value1);
|
||||
}
|
||||
token_pos = 0;
|
||||
if(c == '@' || c == '%') s--;
|
||||
else {
|
||||
char ch[2];
|
||||
ch[0] = (char)c;
|
||||
ch[1] = '\0';
|
||||
my_strcat(_ALLOC_ID_, &result, ch);
|
||||
}
|
||||
state=TOK_BEGIN;
|
||||
} /* else if(state==TOK_SEP) */
|
||||
else if(state==TOK_BEGIN) {
|
||||
char ch[2];
|
||||
ch[0] = (char)c;
|
||||
ch[1] = '\0';
|
||||
my_strcat(_ALLOC_ID_, &result, ch);
|
||||
}
|
||||
if(c=='\0') {
|
||||
my_strcat(_ALLOC_ID_, &result, "");
|
||||
break;
|
||||
}
|
||||
} /* while(1) */
|
||||
dbg(2, "translate3(): returning %s\n", result);
|
||||
my_free(_ALLOC_ID_, &token);
|
||||
|
||||
/* if result is like: 'tcleval(some_string)' pass it thru tcl evaluation so expressions
|
||||
* can be calculated */
|
||||
my_strdup2(_ALLOC_ID_, &translated_tok, tcl_hook2(result));
|
||||
return translated_tok;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1557,6 +1557,7 @@ extern char *find_nth(const char *str, const char *sep, const char *quote, int k
|
|||
extern int isonlydigit(const char *s);
|
||||
extern const char *translate(int inst, const char* s);
|
||||
extern const char* translate2(Lcc *lcc, int level, char* s);
|
||||
extern const char *translate3(const char* s, const char *s1, const char *s2, const char *s3);
|
||||
extern void print_tedax_element(FILE *fd, int inst);
|
||||
extern int print_spice_element(FILE *fd, int inst);
|
||||
extern void print_spice_subckt_nodes(FILE *fd, int symbol);
|
||||
|
|
|
|||
Loading…
Reference in New Issue