Visual analysis setup for Ngspice.
This commit is contained in:
parent
8c2c9c34e5
commit
bc8d9d480a
|
|
@ -47,7 +47,7 @@ install: FORCE
|
|||
$(SCCBOX) install -f -d gschem_import/sym/*.sym "$(XDOCDIR)"/gschem_import/sym
|
||||
$(SCCBOX) install -f -d analyses/*.sch "$(XDOCDIR)"/analyses
|
||||
$(SCCBOX) install -f -d analyses/*.sym "$(XDOCDIR)"/analyses
|
||||
$(SCCBOX) install -f -d analyses/*.init.tcl "$(XDOCDIR)"/analyses
|
||||
$(SCCBOX) install -f -d analyses/lib_init.tcl "$(XDOCDIR)"/analyses
|
||||
$(SCCBOX) install -f -d analyses/README.md "$(XDOCDIR)"/analyses
|
||||
|
||||
uninstall: FORCE
|
||||
|
|
|
|||
|
|
@ -1,41 +1,74 @@
|
|||
# Visual simulation setup library
|
||||
|
||||
This library makes it possible to set up simulations in a way similar to that in Qucs. Each analysis is represented by a symbol. Symbols (e.g. `op.sym`, `ac.sym`, ...) have attributes that specify the analysis parameters. The instances of these symbols are netlisted as commands in the control block of VACASK/Ngspice. The ordering is specified by the `order` attribute. If `order` is not set, 0 is assumed. The symbols (blocks) are netlisted in the ascending `order`.
|
||||
This library makes it possible to set up simulations in a way similar to that in Qucs. Each analysis is represented by a symbol. Symbols (e.g. `op.sym`, `ac.sym`, ...) have attributes that specify the analysis parameters. The instances of these symbols are netlisted as commands in the control block of VACASK/Ngspice. The ordering is specified by the `order` attribute. If `order` is not set, 0 is assumed. The symbols (blocks) are netlisted in the ascending order based on the `order` atttribute.
|
||||
|
||||
Each block displays only those attributes that are specified (i.e. the string length is>0). Netlisting is triggered by the `command_block.sym` block. In order for the netlister to generate the control block you have to place it in the schematic exactly once. In order for netlisting to work you have to source the `analyses.init.tcl` script at Xschem startup by adding the following line to xschemrc.
|
||||
Each block displays only those attributes that are specified (i.e. the string length is>0). Netlisting is triggered by the `command_block.sym` block. In order for the netlister to generate the control block you have to place it in the schematic exactly once. In order for netlisting and symbol rendering to work you have to source the `analyses.init.tcl` script at Xschem startup by adding the following line to xschemrc.
|
||||
```
|
||||
source analyses.init.tcl
|
||||
append postinit_commands {
|
||||
foreach i $pathlist {
|
||||
if {![catch {source $i/lib_init.tcl} retval]} {
|
||||
puts "Sourced library init file $i/lib_init.tcl"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
This will source all `lib_init.tcl` files in all libraries.
|
||||
|
||||
An example that demonstrates the capabilities of this library is in file `demo.sch`.
|
||||
|
||||
|
||||
# Setting up sweeps
|
||||
|
||||
A sweep is defined with an instance of the `sweep.sym` block. Each sweep has a `name` and a `tag` attribute. The `tag` is the name of the variable that will hold the swept values in the simulator's output file (applies only to VACASK). The `name` of the sweep is the one you have to refer to in an analysis to make sweep that particular analysis. To sweep an analysis set its `sweep` parameter to the `name` of the sweep that applies to that analysis. Each `sweep.sym` instance has a `sweep` parameter. This parameter makes it possible to chain sweeps and form multidimensional sweeps.
|
||||
|
||||
For Ngspice sweeps are supported only for the operating point analysis where they are limited to a maximum of 2 dimensions.
|
||||
|
||||
|
||||
# Available analyses
|
||||
|
||||
The following analyses are supported
|
||||
|
||||
|Symbol |VACASK |Ngspice |
|
||||
|-----------|----------------|-----------|
|
||||
|op.sym |op |op |
|
||||
|dc1d.sym |1D sweep of op |dc (1D) |
|
||||
|dcinc.sym |dcinc |- |
|
||||
|dcxf.sym |dcxf |tf |
|
||||
|ac.sym |ac |ac |
|
||||
|acxf.sym |acxf |- |
|
||||
|noise.sym |noise |noise |
|
||||
|tran.sym |tran |tran |
|
||||
|hb.sym |hb |- |
|
||||
|Symbol |Analysis |VACASK |Ngspice |
|
||||
|----------|----------------------------------|------------|--------|
|
||||
|op.sym |operating point |op |op |
|
||||
|dc1d.sym |1D operating point sweep |1D sweep+op |dc (1D) |
|
||||
|dcinc.sym |small signal dc |dcinc |- |
|
||||
|dcxf.sym |small signal dc transfer function |dcxf |tf |
|
||||
|ac.sym |small signal ac |ac |ac |
|
||||
|acxf.sym |small signal ac transfer function |acxf |- |
|
||||
|noise.sym |small signal noise |noise |noise |
|
||||
|tran.sym |transient |tran |tran |
|
||||
|hb.sym |harmonc balance |hb |- |
|
||||
|
||||
|
||||
# Verbatim blocks
|
||||
|
||||
To put verbatim text in a control block the `verbatim.sym` block can be used. The `simulator` attribute specifies the simulator for which the block will be netlisted. If the attribute is not specified the block is netlisted for all simulators. The contents of the block are specified by the `verbatim` attribute.
|
||||
|
||||
|
||||
# Postprocessing scripts
|
||||
Postprocessing scripts can be invoked with instances of the the `postproc.sym` block. The `tool` attribute specifies the (double-quoted) external program to invoke. The `file` attribute specifies the (double-quoted) name of the file that will be passed to the tool. If unquoted `PYTHON` is specified as the `tool` the `python3` interpreter is invoked under Linux and `python.exe` is invoked under Windows.
|
||||
# Sweeps and quoting
|
||||
|
||||
If you want to sweep an analysis, set its `sweep` attribute to the name of the sweep instance (`sweep.sym`). Nested sweeps are specified by setting the `sweep` attribute of a sweep instance. Ngspice has only limited sweeping support (maximal sweep depth is 2, sweeps are allowed only in operating point analysis, you cannot sweep arbitrary parameters).
|
||||
|
||||
All attribute values must be specified in double quotes. Some attributes values must include quotes (must be quoted). When quoting attributes the quotes must be escaped with a backslash (`\"`). The `name` and the `sweep` attribute should not be quoted. All other string attributes must be quoted. The `ic` and `nodeset` attributes (VACASK netlists) should be quoted if they represent the name of the store with stored operating point solution. When explicitly specifying nodesets and initial conditions these attributes should not be quoted.
|
||||
|
||||
|
||||
# Specifying outputs
|
||||
|
||||
For VACASK netlists differential outputs (dcxf, acxf, and noise analyses) are specified with the `outp` and `outn` attributes. These attributes are strings and must be quoted. If the output is a current, specify its name (i.e. `vname.flow(br)`) under `outp` and leave `outn` empty. In both cases `outp` and `outn` values must be quoted.
|
||||
|
||||
For Ngspice netlists differential outputs can be specified either in the same way as for VACASK. An alternative is to specify the output descriptor in SPICE3 style with `outp` (`v(a)`, `v(a,b)`, or `i(vname)`) while leaving `outn` empty. In this case do not quote the value of `outp`.
|
||||
|
||||
|
||||
# Postprocessing scripts
|
||||
|
||||
Postprocessing scripts can be invoked with instances of the the `postproc.sym` block. The `tool` attribute specifies the quoted external program to invoke. The `file` attribute specifies the quoted name of the file that will be passed to the tool. If `tool` is not quoted and its value is `PYTHON` the `python3` interpreter is invoked under Linux and `python.exe` is invoked under Windows.
|
||||
|
||||
|
||||
# Ngspice netlisting notes
|
||||
|
||||
Nodesets and initial conditions specified with the `nodeset` and `ic` attributes are ignored. Nodesets and initial conditions must be specified with ˙.nodeset˙ and ˙.ic˙ directives in a verbatim block.
|
||||
|
||||
A dcxf block runs the TF analysis. The value of the `in` attribute specifies the quoted name of the input source. This attribute is ignored in VACASK netlists because VACASK computes the transfer functions from all independent sources to the given output.
|
||||
|
||||
For the noise block the number of points per summary can be set with the `ptssum` attribute. This attribute is ignored in VACASK netlists.
|
||||
|
|
|
|||
|
|
@ -153,7 +153,7 @@ step=""
|
|||
mode="\\"dec\\""
|
||||
points="10"
|
||||
values=""
|
||||
ptssum=""
|
||||
ptssum="1"
|
||||
nodeset=""
|
||||
store=""
|
||||
write=""
|
||||
|
|
|
|||
|
|
@ -206,15 +206,25 @@ proc netlister {netlist_type} {
|
|||
set suffix [string range $type [string length $prefix] end]
|
||||
# Construct formatter function name
|
||||
set func [join [list "format_" "$suffix" "_" "$netlist_type"] ""]
|
||||
#try {
|
||||
set cmd [$func $name]
|
||||
if {[string length $cmd] > 0} {
|
||||
lappend blocks [format_sweep_chain_$netlist_type $name $cmd types]
|
||||
try {
|
||||
# Format analysis and post analysis script
|
||||
set retval [$func $name]
|
||||
if {[llength $retval] == 2} {
|
||||
lassign $retval cmd postcmd
|
||||
} else {
|
||||
set cmd $retval
|
||||
set postcmd ""
|
||||
}
|
||||
#} on error (msg) {
|
||||
# puts "Error during formatting command $name"
|
||||
# continue
|
||||
#}
|
||||
# Format sweep and add it to analysis
|
||||
set swcmd [format_sweep_chain_$netlist_type $name $cmd types]
|
||||
# Wrap (swept) analysis and post analysis script in a block
|
||||
if {[string length $swcmd] > 0} {
|
||||
lappend blocks [wrap_analysis_$netlist_type $swcmd $postcmd]
|
||||
}
|
||||
} on error msg {
|
||||
puts "Error formatting $name: $msg"
|
||||
continue
|
||||
}
|
||||
}
|
||||
return [wrap_control_$netlist_type $blocks]
|
||||
}
|
||||
|
|
@ -224,9 +234,14 @@ proc netlister {netlist_type} {
|
|||
# Netlister for VACASK
|
||||
#
|
||||
|
||||
# Wrap analysis
|
||||
proc wrap_analysis_spectre {cmds postcmd} {
|
||||
return "$cmds"
|
||||
}
|
||||
|
||||
# Wrap in control block
|
||||
proc wrap_control_spectre {cmds} {
|
||||
set control [indent [join $cmds "\n"] " "]
|
||||
set control [indent [join $cmds "\n\n"] " "]
|
||||
return [join [list "//// begin user architecture code" "control" "$control" "endc" "//// end user architecture code"] "\n"]
|
||||
}
|
||||
|
||||
|
|
@ -241,7 +256,7 @@ proc format_sweep_chain_spectre {name anstr types} {
|
|||
# Yes, reverse sweep chain
|
||||
set sweeplist [lreverse $sweeplist]
|
||||
# Join sweeps
|
||||
set sweeps [join $sweeplist "\n"]
|
||||
set sweeps [join "$sweeplist" "\n"]
|
||||
return "$sweeps\n $anstr"
|
||||
} else {
|
||||
return "$anstr"
|
||||
|
|
@ -261,10 +276,9 @@ proc format_sweep_spectre {parent sweeplist types} {
|
|||
# Sweep has tag property
|
||||
try {
|
||||
lappend swl [format_single_sweep_spectre $sweep]
|
||||
} on error (msg) {
|
||||
} on error msg {
|
||||
# Stop traversing chain on error
|
||||
puts "Error during formating command $sweep"
|
||||
return
|
||||
error "$sweep: $msg"
|
||||
}
|
||||
# Recursion into parent sweep
|
||||
format_sweep_spectre $sweep swl typesdict
|
||||
|
|
@ -299,7 +313,7 @@ proc format_verbatim_spectre {name} {
|
|||
if {[sim_is_$sim]} {
|
||||
set dump true
|
||||
}
|
||||
} on error (msg) {}
|
||||
} on error msg {}
|
||||
}
|
||||
if { !$dump } {
|
||||
return ""
|
||||
|
|
@ -377,7 +391,7 @@ proc format_analysis_hb_spectre {name} {
|
|||
proc format_postprocess_spectre {name} {
|
||||
set tool [format_args $name [list tool NV]]
|
||||
set file [format_args $name [list file NV]]
|
||||
return "postprocess($tool, $file)"
|
||||
return [list "postprocess($tool, $file)" ""]
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -385,10 +399,25 @@ proc format_postprocess_spectre {name} {
|
|||
# Netlister for Ngspice
|
||||
#
|
||||
|
||||
# Wrap analysis
|
||||
proc wrap_analysis_spice {cmds postcmd} {
|
||||
set txt ""
|
||||
if {[string length $postcmd] > 0} {
|
||||
append txt "destroy all\n"
|
||||
}
|
||||
append txt $cmds
|
||||
if {[string length $postcmd] > 0} {
|
||||
# Write only if analysis succeeded
|
||||
# append txt "\nif $#plots gt 1\n$postcmd\nend"
|
||||
append txt "\n$postcmd"
|
||||
}
|
||||
return $txt
|
||||
}
|
||||
|
||||
# Wrap in control block
|
||||
proc wrap_control_spice {cmds} {
|
||||
set control [join $cmds "\n"]
|
||||
return [join [list "**** begin user architecture code" ".control" "$control" ".endc" "**** end user architecture code"] "\n"]
|
||||
set control [join $cmds "\n\n"]
|
||||
return [join [list "**** begin user architecture code" ".control" "set filetype=binary" "" "$control" ".endc" "**** end user architecture code"] "\n"]
|
||||
}
|
||||
|
||||
# Add sweep chain to analysis
|
||||
|
|
@ -411,10 +440,22 @@ proc format_sweep_chain_spice {name anstr types} {
|
|||
set sweep [ xschem getprop instance $name sweep ]
|
||||
set sweeplist {}
|
||||
format_sweep_spice $decoctlin $name sweeplist typesdict
|
||||
# TODO: maximal sweep chain depths
|
||||
# - op 2
|
||||
# - dc1d 1
|
||||
# - all others 0
|
||||
# Limit sweep dimension for analyses
|
||||
if {[string match "netlist_command_analysis_*" $antype]} {
|
||||
if {$antype eq "netlist_command_analysis_op"} {
|
||||
if {[llength $sweeplist] > 2} {
|
||||
error "sweep dimension can be at most 2"
|
||||
}
|
||||
} elseif {$antype eq "netlist_command_analysis_dc1d"} {
|
||||
if {[llength $sweeplist] > 1} {
|
||||
error "sweep dimension can be at most 2"
|
||||
}
|
||||
} else {
|
||||
if {[llength $sweeplist] > 0} {
|
||||
error "sweep is not suported"
|
||||
}
|
||||
}
|
||||
}
|
||||
# Do we have any sweeps
|
||||
if {[llength $sweeplist] > 0} {
|
||||
# Yes, join sweeps
|
||||
|
|
@ -438,10 +479,9 @@ proc format_sweep_spice {decoctlin parent sweeplist types} {
|
|||
# Sweep has tag property
|
||||
try {
|
||||
lappend swl [format_single_sweep_spice $decoctlin $sweep]
|
||||
} on error (msg) {
|
||||
} on error msg {
|
||||
# Stop traversing chain on error
|
||||
puts "Error during formating command $sweep"
|
||||
return
|
||||
error "$sweep: $msg"
|
||||
}
|
||||
# Recursion into parent sweep
|
||||
format_sweep_spice $decoctlin $sweep swl typesdict
|
||||
|
|
@ -468,23 +508,26 @@ proc format_sweep_spice_range {decoctlin name} {
|
|||
}
|
||||
}
|
||||
|
||||
# Each formatter returns a list with two elements
|
||||
# - analysis
|
||||
# - rawfile write script / post-command script
|
||||
|
||||
proc format_verbatim_spice {name} {
|
||||
return [format_verbatim_spectre $name]
|
||||
return [list [format_verbatim_spectre $name] ""]
|
||||
}
|
||||
|
||||
proc format_analysis_op_spice {name} {
|
||||
return "op"
|
||||
return [list "op" "write $name.raw"]
|
||||
}
|
||||
|
||||
proc format_analysis_dc1d_spice {name} {
|
||||
# 1D sweep formatting
|
||||
set swp [format_single_sweep_spice false $name]
|
||||
return "dc $swp"
|
||||
return [list "dc $swp" "write $name.raw"]
|
||||
}
|
||||
|
||||
proc format_analysis_dcinc_spice {name} {
|
||||
puts "$name: dcinc is not supported by Ngspice"
|
||||
return ""
|
||||
error "dcinc is not supported by Ngspice"
|
||||
}
|
||||
|
||||
proc format_signal_output_spice {name} {
|
||||
|
|
@ -515,23 +558,23 @@ proc format_signal_output_spice {name} {
|
|||
|
||||
proc format_analysis_dcxf_spice {name} {
|
||||
set output "[format_signal_output_spice $name]"
|
||||
return "tf $output [format_args $name [list in UNV]]"
|
||||
return [list "tf $output [format_args $name [list in UNV]]" "write $name.raw"]
|
||||
}
|
||||
|
||||
proc format_analysis_ac_spice {name} {
|
||||
set swp "[format_sweep_spice_range true $name] "
|
||||
return "ac $swp"
|
||||
return [list "ac $swp" "write $name.raw"]
|
||||
}
|
||||
|
||||
proc format_analysis_acxf_spice {name} {
|
||||
puts "$name: acxf is not supported by Ngspice"
|
||||
return ""
|
||||
error "acxf is not supported by Ngspice"
|
||||
}
|
||||
|
||||
proc format_analysis_noise_spice {name} {
|
||||
set output "[format_signal_output_spice $name]"
|
||||
set swp "[format_sweep_spice_range true $name] "
|
||||
return "noise $output [format_args $name [list in UNV]] $swp [format_args $name [list ptssum NV]]"
|
||||
set swp "[format_sweep_spice_range true $name]"
|
||||
set writer "write $name-integrated.raw\nsetplot previous\nwrite $name.raw"
|
||||
return [list "noise $output [format_args $name [list in UNV]] $swp [format_args $name [list ptssum NV]]" "$writer"]
|
||||
}
|
||||
|
||||
proc format_analysis_tran_spice {name} {
|
||||
|
|
@ -540,21 +583,17 @@ proc format_analysis_tran_spice {name} {
|
|||
if {$icmode eq "uic"} {
|
||||
append args " uic"
|
||||
}
|
||||
return "tran $args"
|
||||
return [list "tran $args" "write $name.raw"]
|
||||
}
|
||||
|
||||
proc format_analysis_hb_spice {name} {
|
||||
puts "$name: hb is not supported by Ngspice"
|
||||
return ""
|
||||
error "hb is not supported by Ngspice"
|
||||
}
|
||||
|
||||
proc format_postprocess_spice {name} {
|
||||
global tcl_platform
|
||||
set tool [format_args $name [list tool NV]]
|
||||
if {[string match "\"*\"" $tool]} {
|
||||
# Quoted, unquote, use literally
|
||||
set tool [string range $tool 1 end-1]
|
||||
} else {
|
||||
if {![string match "\"*\"" $tool]} {
|
||||
# Not quoted, check if it is PYTHON (VACASK variable for autodetected Python)
|
||||
if {$tool eq "PYTHON"} {
|
||||
if {$tcl_platform(platform) eq "windows"} {
|
||||
|
|
@ -564,13 +603,10 @@ proc format_postprocess_spice {name} {
|
|||
}
|
||||
}
|
||||
}
|
||||
# Keep quotes around file
|
||||
# Keep quotes around tool and file
|
||||
set file [format_args $name [list file NV]]
|
||||
return "shell $tool $file"
|
||||
return [list "shell $tool $file" ""]
|
||||
}
|
||||
|
||||
|
||||
|
||||
# TODO: add ngspice formatting
|
||||
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue