various improvements for automatic port order detection from included subcircuit via spice_sym_def and @pinlist in format string, documentation updates in tutorial_use_existing_subckt.html
This commit is contained in:
parent
d2c6566030
commit
0597bae9dc
|
|
@ -211,6 +211,11 @@ type=nmos
|
|||
verilog_sym_def="tcleval(`include \"[abs_sym_path verilog_include_file.v]\")"
|
||||
</pre>
|
||||
</p>
|
||||
<p class="important">
|
||||
For spice netlists if <kbd>@pinlist</kbd> is used in format string and <kbd>spice_sym_def</kbd> attribute
|
||||
is defined the port order will be derived from the subcircuit
|
||||
referenced by the <kbd>spice_sym_def</kbd> attribute.
|
||||
</p>
|
||||
<p>
|
||||
In this example a <kbd>verilog_include_file.v</kbd> is included using the verilog <kbd>`include</kbd> directive.
|
||||
In order to generate a full path for it the <kbd>abs_sym_path</kbd> TCL function is used that searches for this file
|
||||
|
|
|
|||
|
|
@ -132,6 +132,61 @@ format="@name @@GND @@TRIG @@OUT @@RESETB @@CTRL @@THRES @@DIS @@VCC @symname"
|
|||
is <b>named</b> and not <b>positional</b>.
|
||||
</p>
|
||||
</li>
|
||||
|
||||
|
||||
<a id="spice_sym_def">
|
||||
<li>
|
||||
<h3> Obtaining the pin ordering from the subcircuit definition specified via <kbd>spice_sym_def</kbd></h3>
|
||||
<p>
|
||||
For spice netlists if <kbd>@pinlist</kbd> is specified in format string and a symbol <kbd>spice_sym_def</kbd>
|
||||
attribute is used then the order of the symbol ports will be obtained from the <kbd>.subckt</kbd> specified
|
||||
by <kbd>spice_sym_def</kbd>, either directly or via a <kbd>.include</kbd> statement
|
||||
</p>
|
||||
<img src="tutorial_use_existing_subckt08.png">
|
||||
<p>
|
||||
The <kbd>symbol_include.cir</kbd> file has the following content:
|
||||
</p>
|
||||
<pre class="code">
|
||||
* example of a subcircuit contained in a file
|
||||
|
||||
.subckt symbol_include Z VCC VSS
|
||||
+ A B C W=10 L=1
|
||||
...
|
||||
...
|
||||
.ends
|
||||
</pre>
|
||||
<p>
|
||||
And as a result the following circuit:
|
||||
</p>
|
||||
<img src="tutorial_use_existing_subckt09.png">
|
||||
<p>
|
||||
is netlisted in the following way, notice the net assignment in the <kbd>x1</kbd> subcircuit call
|
||||
matches the order in the <kbd>symbol_include.cir</kbd> file:
|
||||
</p>
|
||||
<pre class="code">
|
||||
** sch_path: /home/schippes/.xschem/xschem_library/symbol_include/tb_symbol_include.sch
|
||||
**.subckt tb_symbol_include XZ XVSS XVCC XC XB XA
|
||||
*.opin XZ
|
||||
*.ipin XVSS
|
||||
*.ipin XVCC
|
||||
*.ipin XC
|
||||
*.ipin XB
|
||||
*.ipin XA
|
||||
x1 XZ XVCC XVSS XA XB XC symbol_include
|
||||
**.ends
|
||||
|
||||
* expanding symbol: symbol_include.sym # of pins=6
|
||||
** sym_path: /home/schippes/.xschem/xschem_library/symbol_include/symbol_include.sym
|
||||
.include symbol_include.cir
|
||||
.end
|
||||
</pre>
|
||||
|
||||
|
||||
</li>
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</ol>
|
||||
|
||||
<h2>Specifying subcircuit netlist</h2>
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 50 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 47 KiB |
|
|
@ -1848,7 +1848,6 @@ void get_additional_symbols(int what)
|
|||
Int_hashentry *found;
|
||||
Int_hashtable sym_table = {NULL, 0};
|
||||
|
||||
|
||||
if(what == 1) { /* start */
|
||||
int_hash_init(&sym_table, HASHSIZE);
|
||||
num_syms = xctx->symbols;
|
||||
|
|
@ -1904,15 +1903,18 @@ void get_additional_symbols(int what)
|
|||
my_strdup(_ALLOC_ID_, &xctx->sym[j].prop_ptr,
|
||||
subst_token(xctx->sym[j].prop_ptr, "default_schematic", NULL)); /* delete attribute */
|
||||
}
|
||||
if(spice_sym_def)
|
||||
if(spice_sym_def) {
|
||||
my_strdup(_ALLOC_ID_, &xctx->sym[j].prop_ptr,
|
||||
subst_token(xctx->sym[j].prop_ptr, "spice_sym_def", spice_sym_def));
|
||||
if(verilog_sym_def)
|
||||
}
|
||||
if(verilog_sym_def) {
|
||||
my_strdup(_ALLOC_ID_, &xctx->sym[j].prop_ptr,
|
||||
subst_token(xctx->sym[j].prop_ptr, "verilog_sym_def", verilog_sym_def));
|
||||
if(vhdl_sym_def)
|
||||
}
|
||||
if(vhdl_sym_def) {
|
||||
my_strdup(_ALLOC_ID_, &xctx->sym[j].prop_ptr,
|
||||
subst_token(xctx->sym[j].prop_ptr, "vhdl_sym_def", vhdl_sym_def));
|
||||
}
|
||||
xctx->symbols++;
|
||||
} else {
|
||||
j = found->value;
|
||||
|
|
|
|||
49
src/token.c
49
src/token.c
|
|
@ -1815,52 +1815,67 @@ void print_tedax_subckt(FILE *fd, int symbol)
|
|||
/* This function is used to generate the @pinlist replacement getting port order
|
||||
* from the spice_sym_def attribute (either directly or by loading the provided .include file),
|
||||
* checking with the corresponding symbol pin name and getting the net name attached to it.
|
||||
* Any name mismatch is reported and in this case the function does nothing. The default xschem
|
||||
* Any name mismatch is reported, in this case the function does nothing and the default xschem
|
||||
* symbol port ordering will be used. */
|
||||
static int has_included_subcircuit(int inst, int symbol, char **result)
|
||||
{
|
||||
char *spice_sym_def = NULL;
|
||||
int ret = 0;
|
||||
|
||||
my_strdup2(_ALLOC_ID_, &spice_sym_def, get_tok_value(xctx->sym[symbol].prop_ptr, "spice_sym_def", 0));
|
||||
my_strdup2(_ALLOC_ID_, &spice_sym_def, get_tok_value(xctx->inst[inst].prop_ptr, "spice_sym_def", 0));
|
||||
if(!spice_sym_def[0]) {
|
||||
my_strdup2(_ALLOC_ID_, &spice_sym_def, get_tok_value(xctx->sym[symbol].prop_ptr, "spice_sym_def", 0));
|
||||
}
|
||||
if(xctx->tok_size) {
|
||||
tclvareval("has_included_subcircuit {", spice_sym_def, "}", NULL);
|
||||
tclvareval("has_included_subcircuit {", get_cell(xctx->sym[symbol].name, 0), "} {",
|
||||
spice_sym_def, "}", NULL);
|
||||
if(tclresult()[0]) {
|
||||
char *pinlist = NULL;
|
||||
char *pin, *save;
|
||||
char *pinlist_ptr;
|
||||
const char *net;
|
||||
char *tmp_result = NULL;
|
||||
int i, no_of_pins = (xctx->inst[inst].ptr + xctx->sym)->rects[PINLAYER], multip;
|
||||
int symbol_pins = 0;
|
||||
int instance_pins = 0;
|
||||
Int_hashentry *entry;
|
||||
Int_hashtable table = {NULL, 0};
|
||||
int_hash_init(&table, 37);
|
||||
|
||||
for(i = 0;i < no_of_pins; ++i) {
|
||||
char *prop = (xctx->inst[inst].ptr + xctx->sym)->rect[PINLAYER][i].prop_ptr;
|
||||
int spice_ignore = !strboolcmp(get_tok_value(prop, "spice_ignore", 0), "true");
|
||||
const char *name = get_tok_value(prop, "name", 0);
|
||||
if(!spice_ignore) {
|
||||
int_hash_lookup(&table, name, i, XINSERT_NOREPLACE);
|
||||
}
|
||||
}
|
||||
|
||||
my_strdup2(_ALLOC_ID_, &pinlist, tclresult());
|
||||
dbg(1, "included subcircuit: pinlist=%s\n", pinlist);
|
||||
pinlist_ptr = pinlist;
|
||||
while( (pin = my_strtok_r(pinlist_ptr, " ", "", 0, &save)) ) {
|
||||
instance_pins++;
|
||||
for(i = 0;i < no_of_pins; ++i) {
|
||||
char *prop = (xctx->inst[inst].ptr + xctx->sym)->rect[PINLAYER][i].prop_ptr;
|
||||
int spice_ignore = !strboolcmp(get_tok_value(prop, "spice_ignore", 0), "true");
|
||||
const char *name = get_tok_value(prop, "name", 0);
|
||||
|
||||
if(!spice_ignore) {
|
||||
if(!strcmp(pin, name)) {
|
||||
symbol_pins++;
|
||||
net = net_name(inst, i, &multip, 0, 1);
|
||||
my_mstrcat(_ALLOC_ID_, result, "?", my_itoa(multip), " ", net, " ", NULL);
|
||||
}
|
||||
}
|
||||
entry = int_hash_lookup(&table, pin, 0, XLOOKUP);
|
||||
if(entry) {
|
||||
i = entry->value;
|
||||
symbol_pins++;
|
||||
net = net_name(inst, i, &multip, 0, 1);
|
||||
my_mstrcat(_ALLOC_ID_, &tmp_result, "?", my_itoa(multip), " ", net, " ", NULL);
|
||||
}
|
||||
pinlist_ptr = NULL;
|
||||
}
|
||||
if(instance_pins == symbol_pins) ret = 1;
|
||||
else {
|
||||
int_hash_free(&table);
|
||||
if(instance_pins == symbol_pins) {
|
||||
ret = 1;
|
||||
my_mstrcat(_ALLOC_ID_, result, tmp_result, NULL);
|
||||
} else {
|
||||
dbg(0, "has_included_subcircuit(): symbol and .subckt pins do not match. Discard .subckt port order\n");
|
||||
if(has_x)
|
||||
tcleval("alert_ {has_included_subcircuit(): "
|
||||
"symbol and .subckt pins do not match. Discard .subckt port order}");
|
||||
}
|
||||
if(tmp_result) my_free(_ALLOC_ID_, &tmp_result);
|
||||
my_free(_ALLOC_ID_, &pinlist);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -656,14 +656,17 @@ proc ev0 {args} {
|
|||
|
||||
# get pin ordering from included subcircuit
|
||||
# return empty string if not found.
|
||||
proc has_included_subcircuit {spice_sym_def} {
|
||||
proc has_included_subcircuit {symname spice_sym_def} {
|
||||
global has_x
|
||||
set include_found 0
|
||||
# puts "has_included_subcircuit: spice_sym_def=$spice_sym_def"
|
||||
regsub -all {\n\+} $spice_sym_def { } spice_sym_def
|
||||
set pinlist {}
|
||||
# .include? get the file ...
|
||||
if {[regexp -nocase {^\.include } $spice_sym_def]} {
|
||||
set filename [lindex $spice_sym_def 1]
|
||||
if {[regexp -nocase {^ *\.include +} $spice_sym_def]} {
|
||||
regsub -nocase {^ *\.include +} $spice_sym_def {} filename
|
||||
regsub -all {^"|"$} $filename {} filename
|
||||
set filename [abs_sym_path $filename]
|
||||
# puts "filename=$filename"
|
||||
set res [catch {open $filename r} fd]
|
||||
if { $res } {
|
||||
|
|
@ -680,8 +683,10 @@ proc has_included_subcircuit {spice_sym_def} {
|
|||
# split lines
|
||||
set spice_sym_def [split $spice_sym_def \n]
|
||||
foreach line $spice_sym_def {
|
||||
# het 1st line with a .subckt. This is our subcircuit definition, get the pin order
|
||||
if {[string tolower [lindex $line 0]] eq {.subckt} } {
|
||||
# get 1st line with a matching .subckt. This is our subcircuit definition, get the pin order
|
||||
if {[string tolower [lindex $line 0]] eq {.subckt} &&
|
||||
[string tolower [lindex $line 1]] eq $symname} {
|
||||
set include_found 1
|
||||
regsub -all { *= *} $line {=} line
|
||||
# pin list ends where parameter assignment begins (param=value)
|
||||
set last [lsearch -regexp [string tolower $line] {=|param:}]
|
||||
|
|
@ -695,6 +700,12 @@ proc has_included_subcircuit {spice_sym_def} {
|
|||
}
|
||||
}
|
||||
# return pinlist as found in the .subckt line or empty string if not found
|
||||
if {!$include_found} {
|
||||
puts "has_included_subcircuit: no matching .subckt found in spice_sym_def. Ignore"
|
||||
if { [info exists has_x] } {
|
||||
alert_ "has_included_subcircuit: no matching .subckt found in spice_sym_def. Ignore"
|
||||
}
|
||||
}
|
||||
return $pinlist
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue