Add new spice regression test for windows path separators.
This commit is contained in:
parent
542719c753
commit
6053b86a24
|
@ -0,0 +1,334 @@
|
|||
{
|
||||
"board": {
|
||||
"3dviewports": [],
|
||||
"design_settings": {
|
||||
"defaults": {
|
||||
"board_outline_line_width": 0.1,
|
||||
"copper_line_width": 0.2,
|
||||
"copper_text_size_h": 1.5,
|
||||
"copper_text_size_v": 1.5,
|
||||
"copper_text_thickness": 0.3,
|
||||
"other_line_width": 0.15,
|
||||
"silk_line_width": 0.15,
|
||||
"silk_text_size_h": 1.0,
|
||||
"silk_text_size_v": 1.0,
|
||||
"silk_text_thickness": 0.15
|
||||
},
|
||||
"diff_pair_dimensions": [],
|
||||
"drc_exclusions": [],
|
||||
"rules": {
|
||||
"min_copper_edge_clearance": 0.0,
|
||||
"solder_mask_clearance": 0.0,
|
||||
"solder_mask_min_width": 0.0
|
||||
},
|
||||
"track_widths": [],
|
||||
"via_dimensions": []
|
||||
},
|
||||
"layer_presets": [],
|
||||
"viewports": []
|
||||
},
|
||||
"boards": [],
|
||||
"cvpcb": {
|
||||
"equivalence_files": []
|
||||
},
|
||||
"erc": {
|
||||
"erc_exclusions": [],
|
||||
"meta": {
|
||||
"version": 0
|
||||
},
|
||||
"pin_map": [
|
||||
[
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
2,
|
||||
1,
|
||||
1,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
2,
|
||||
1,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
2,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2
|
||||
]
|
||||
],
|
||||
"rule_severities": {
|
||||
"bus_definition_conflict": "error",
|
||||
"bus_entry_needed": "error",
|
||||
"bus_label_syntax": "error",
|
||||
"bus_to_bus_conflict": "error",
|
||||
"bus_to_net_conflict": "error",
|
||||
"different_unit_footprint": "error",
|
||||
"different_unit_net": "error",
|
||||
"duplicate_reference": "error",
|
||||
"duplicate_sheet_names": "error",
|
||||
"extra_units": "error",
|
||||
"global_label_dangling": "warning",
|
||||
"hier_label_mismatch": "error",
|
||||
"label_dangling": "error",
|
||||
"lib_symbol_issues": "warning",
|
||||
"multiple_net_names": "warning",
|
||||
"net_not_bus_member": "warning",
|
||||
"no_connect_connected": "warning",
|
||||
"no_connect_dangling": "warning",
|
||||
"pin_not_connected": "error",
|
||||
"pin_not_driven": "error",
|
||||
"pin_to_pin": "warning",
|
||||
"power_pin_not_driven": "error",
|
||||
"similar_labels": "warning",
|
||||
"unannotated": "error",
|
||||
"unit_value_mismatch": "error",
|
||||
"unresolved_variable": "error",
|
||||
"wire_dangling": "error"
|
||||
}
|
||||
},
|
||||
"libraries": {
|
||||
"pinned_footprint_libs": [],
|
||||
"pinned_symbol_libs": []
|
||||
},
|
||||
"meta": {
|
||||
"filename": "sim2_V6.kicad_pro",
|
||||
"version": 1
|
||||
},
|
||||
"net_settings": {
|
||||
"classes": [
|
||||
{
|
||||
"bus_width": 12.0,
|
||||
"clearance": 0.2,
|
||||
"diff_pair_gap": 0.25,
|
||||
"diff_pair_via_gap": 0.25,
|
||||
"diff_pair_width": 0.2,
|
||||
"line_style": 0,
|
||||
"microvia_diameter": 0.3,
|
||||
"microvia_drill": 0.1,
|
||||
"name": "Default",
|
||||
"pcb_color": "rgba(0, 0, 0, 0.000)",
|
||||
"schematic_color": "rgba(0, 0, 0, 0.000)",
|
||||
"track_width": 0.25,
|
||||
"via_diameter": 0.8,
|
||||
"via_drill": 0.4,
|
||||
"wire_width": 6.0
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"version": 2
|
||||
},
|
||||
"net_colors": null,
|
||||
"netclass_assignments": null,
|
||||
"netclass_patterns": []
|
||||
},
|
||||
"pcbnew": {
|
||||
"last_paths": {
|
||||
"gencad": "",
|
||||
"idf": "",
|
||||
"netlist": "",
|
||||
"specctra_dsn": "",
|
||||
"step": "",
|
||||
"vrml": ""
|
||||
},
|
||||
"page_layout_descr_file": ""
|
||||
},
|
||||
"schematic": {
|
||||
"annotate_start_num": 0,
|
||||
"drawing": {
|
||||
"dashed_lines_dash_length_ratio": 12.0,
|
||||
"dashed_lines_gap_length_ratio": 3.0,
|
||||
"default_line_thickness": 6.0,
|
||||
"default_text_size": 50.0,
|
||||
"field_names": [],
|
||||
"intersheets_ref_own_page": false,
|
||||
"intersheets_ref_prefix": "",
|
||||
"intersheets_ref_short": false,
|
||||
"intersheets_ref_show": false,
|
||||
"intersheets_ref_suffix": "",
|
||||
"junction_size_choice": 3,
|
||||
"label_size_ratio": 0.375,
|
||||
"pin_symbol_size": 25.0,
|
||||
"text_offset_ratio": 0.15
|
||||
},
|
||||
"legacy_lib_dir": "",
|
||||
"legacy_lib_list": [],
|
||||
"meta": {
|
||||
"version": 1
|
||||
},
|
||||
"net_format_name": "",
|
||||
"ngspice": {
|
||||
"fix_include_paths": true,
|
||||
"fix_passive_vals": true,
|
||||
"meta": {
|
||||
"version": 0
|
||||
},
|
||||
"model_mode": 2,
|
||||
"workbook_filename": "sim2_V6.wbk"
|
||||
},
|
||||
"page_layout_descr_file": "",
|
||||
"plot_directory": "",
|
||||
"spice_adjust_passive_values": false,
|
||||
"spice_external_command": "spice \"%I\"",
|
||||
"spice_save_all_currents": false,
|
||||
"spice_save_all_voltages": false,
|
||||
"subpart_first_id": 65,
|
||||
"subpart_id_separator": 0
|
||||
},
|
||||
"sheets": [
|
||||
[
|
||||
"c320d65b-dd35-489c-9c1b-364c21869ec2",
|
||||
""
|
||||
]
|
||||
],
|
||||
"text_variables": {}
|
||||
}
|
|
@ -0,0 +1,429 @@
|
|||
(kicad_sch (version 20211123) (generator eeschema)
|
||||
|
||||
(uuid c320d65b-dd35-489c-9c1b-364c21869ec2)
|
||||
|
||||
(paper "A4")
|
||||
|
||||
(lib_symbols
|
||||
(symbol "Device:D" (pin_numbers hide) (pin_names (offset 1.016) hide) (in_bom yes) (on_board yes)
|
||||
(property "Reference" "D" (id 0) (at 0 2.54 0)
|
||||
(effects (font (size 1.27 1.27)))
|
||||
)
|
||||
(property "Value" "D" (id 1) (at 0 -2.54 0)
|
||||
(effects (font (size 1.27 1.27)))
|
||||
)
|
||||
(property "Footprint" "" (id 2) (at 0 0 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(property "Datasheet" "~" (id 3) (at 0 0 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(property "ki_keywords" "diode" (id 4) (at 0 0 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(property "ki_description" "Diode" (id 5) (at 0 0 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(property "ki_fp_filters" "TO-???* *_Diode_* *SingleDiode* D_*" (id 6) (at 0 0 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(symbol "D_0_1"
|
||||
(polyline
|
||||
(pts
|
||||
(xy -1.27 1.27)
|
||||
(xy -1.27 -1.27)
|
||||
)
|
||||
(stroke (width 0.254) (type default) (color 0 0 0 0))
|
||||
(fill (type none))
|
||||
)
|
||||
(polyline
|
||||
(pts
|
||||
(xy 1.27 0)
|
||||
(xy -1.27 0)
|
||||
)
|
||||
(stroke (width 0) (type default) (color 0 0 0 0))
|
||||
(fill (type none))
|
||||
)
|
||||
(polyline
|
||||
(pts
|
||||
(xy 1.27 1.27)
|
||||
(xy 1.27 -1.27)
|
||||
(xy -1.27 0)
|
||||
(xy 1.27 1.27)
|
||||
)
|
||||
(stroke (width 0.254) (type default) (color 0 0 0 0))
|
||||
(fill (type none))
|
||||
)
|
||||
)
|
||||
(symbol "D_1_1"
|
||||
(pin passive line (at -3.81 0 0) (length 2.54)
|
||||
(name "K" (effects (font (size 1.27 1.27))))
|
||||
(number "1" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin passive line (at 3.81 0 180) (length 2.54)
|
||||
(name "A" (effects (font (size 1.27 1.27))))
|
||||
(number "2" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
)
|
||||
)
|
||||
(symbol "Device:R" (pin_numbers hide) (pin_names (offset 0)) (in_bom yes) (on_board yes)
|
||||
(property "Reference" "R" (id 0) (at 2.032 0 90)
|
||||
(effects (font (size 1.27 1.27)))
|
||||
)
|
||||
(property "Value" "R" (id 1) (at 0 0 90)
|
||||
(effects (font (size 1.27 1.27)))
|
||||
)
|
||||
(property "Footprint" "" (id 2) (at -1.778 0 90)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(property "Datasheet" "~" (id 3) (at 0 0 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(property "ki_keywords" "R res resistor" (id 4) (at 0 0 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(property "ki_description" "Resistor" (id 5) (at 0 0 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(property "ki_fp_filters" "R_*" (id 6) (at 0 0 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(symbol "R_0_1"
|
||||
(rectangle (start -1.016 -2.54) (end 1.016 2.54)
|
||||
(stroke (width 0.254) (type default) (color 0 0 0 0))
|
||||
(fill (type none))
|
||||
)
|
||||
)
|
||||
(symbol "R_1_1"
|
||||
(pin passive line (at 0 3.81 270) (length 1.27)
|
||||
(name "~" (effects (font (size 1.27 1.27))))
|
||||
(number "1" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin passive line (at 0 -3.81 90) (length 1.27)
|
||||
(name "~" (effects (font (size 1.27 1.27))))
|
||||
(number "2" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
)
|
||||
)
|
||||
(symbol "Simulation_SPICE:VPULSE" (pin_numbers hide) (pin_names (offset 0.0254)) (in_bom yes) (on_board yes)
|
||||
(property "Reference" "V" (id 0) (at 2.54 2.54 0)
|
||||
(effects (font (size 1.27 1.27)) (justify left))
|
||||
)
|
||||
(property "Value" "VPULSE" (id 1) (at 2.54 0 0)
|
||||
(effects (font (size 1.27 1.27)) (justify left))
|
||||
)
|
||||
(property "Footprint" "" (id 2) (at 0 0 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(property "Datasheet" "~" (id 3) (at 0 0 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(property "Spice_Netlist_Enabled" "Y" (id 4) (at 0 0 0)
|
||||
(effects (font (size 1.27 1.27)) (justify left) hide)
|
||||
)
|
||||
(property "Spice_Primitive" "V" (id 5) (at 0 0 0)
|
||||
(effects (font (size 1.27 1.27)) (justify left) hide)
|
||||
)
|
||||
(property "Spice_Model" "pulse(0 1 2n 2n 2n 50n 100n)" (id 6) (at 2.54 -2.54 0)
|
||||
(effects (font (size 1.27 1.27)) (justify left))
|
||||
)
|
||||
(property "ki_keywords" "simulation" (id 7) (at 0 0 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(property "ki_description" "Voltage source, pulse" (id 8) (at 0 0 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(symbol "VPULSE_0_0"
|
||||
(polyline
|
||||
(pts
|
||||
(xy -2.032 -0.762)
|
||||
(xy -1.397 -0.762)
|
||||
(xy -1.143 0.762)
|
||||
(xy -0.127 0.762)
|
||||
(xy 0.127 -0.762)
|
||||
(xy 1.143 -0.762)
|
||||
(xy 1.397 0.762)
|
||||
(xy 2.032 0.762)
|
||||
)
|
||||
(stroke (width 0) (type default) (color 0 0 0 0))
|
||||
(fill (type none))
|
||||
)
|
||||
(text "+" (at 0 1.905 0)
|
||||
(effects (font (size 1.27 1.27)))
|
||||
)
|
||||
)
|
||||
(symbol "VPULSE_0_1"
|
||||
(circle (center 0 0) (radius 2.54)
|
||||
(stroke (width 0.254) (type default) (color 0 0 0 0))
|
||||
(fill (type background))
|
||||
)
|
||||
)
|
||||
(symbol "VPULSE_1_1"
|
||||
(pin passive line (at 0 5.08 270) (length 2.54)
|
||||
(name "~" (effects (font (size 1.27 1.27))))
|
||||
(number "1" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin passive line (at 0 -5.08 90) (length 2.54)
|
||||
(name "~" (effects (font (size 1.27 1.27))))
|
||||
(number "2" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
)
|
||||
)
|
||||
(symbol "pspice:0" (power) (pin_names (offset 0)) (in_bom yes) (on_board yes)
|
||||
(property "Reference" "#GND" (id 0) (at 0 -2.54 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(property "Value" "0" (id 1) (at 0 -1.778 0)
|
||||
(effects (font (size 1.27 1.27)))
|
||||
)
|
||||
(property "Footprint" "" (id 2) (at 0 0 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(property "Datasheet" "~" (id 3) (at 0 0 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(property "ki_keywords" "simulation" (id 4) (at 0 0 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(property "ki_description" "0V reference potential for simulation" (id 5) (at 0 0 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(symbol "0_0_1"
|
||||
(polyline
|
||||
(pts
|
||||
(xy -1.27 0)
|
||||
(xy 0 -1.27)
|
||||
(xy 1.27 0)
|
||||
(xy -1.27 0)
|
||||
)
|
||||
(stroke (width 0) (type default) (color 0 0 0 0))
|
||||
(fill (type none))
|
||||
)
|
||||
)
|
||||
(symbol "0_1_1"
|
||||
(pin power_in line (at 0 0 0) (length 0) hide
|
||||
(name "0" (effects (font (size 1.016 1.016))))
|
||||
(number "1" (effects (font (size 1.016 1.016))))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
(text ".tran 1us 1ms" (at 142.24 63.5 0)
|
||||
(effects (font (size 1.27 1.27)) (justify left bottom))
|
||||
(uuid 14103cc0-6e61-4ce0-83d2-854b9063d98e)
|
||||
)
|
||||
|
||||
(junction (at 96.52 63.5) (diameter 0) (color 0 0 0 0)
|
||||
(uuid cd3bc7f1-e10c-4d40-aa30-03430340cec2)
|
||||
)
|
||||
|
||||
(wire (pts (xy 76.2 63.5) (xy 96.52 63.5))
|
||||
(stroke (width 0) (type default) (color 0 0 0 0))
|
||||
(uuid 02ecd695-b1f0-43ff-8105-c2eee8a924e0)
|
||||
)
|
||||
(wire (pts (xy 68.58 63.5) (xy 49.53 63.5))
|
||||
(stroke (width 0) (type default) (color 0 0 0 0))
|
||||
(uuid 199035fe-3d65-490e-9880-3fcdb007162e)
|
||||
)
|
||||
(wire (pts (xy 110.49 73.66) (xy 110.49 63.5))
|
||||
(stroke (width 0) (type default) (color 0 0 0 0))
|
||||
(uuid 215ac09b-1d70-4686-a946-5aba79aff49c)
|
||||
)
|
||||
(wire (pts (xy 96.52 91.44) (xy 96.52 81.28))
|
||||
(stroke (width 0) (type default) (color 0 0 0 0))
|
||||
(uuid 43b501d1-3d64-4f8e-ba9c-39ed115faf74)
|
||||
)
|
||||
(wire (pts (xy 110.49 63.5) (xy 96.52 63.5))
|
||||
(stroke (width 0) (type default) (color 0 0 0 0))
|
||||
(uuid 6839711f-d909-4163-b101-e6e468058419)
|
||||
)
|
||||
(wire (pts (xy 110.49 91.44) (xy 110.49 81.28))
|
||||
(stroke (width 0) (type default) (color 0 0 0 0))
|
||||
(uuid 84e89c8f-a4c5-417c-a59f-c74d16e4650a)
|
||||
)
|
||||
(wire (pts (xy 49.53 91.44) (xy 49.53 81.28))
|
||||
(stroke (width 0) (type default) (color 0 0 0 0))
|
||||
(uuid ba6e88b9-4c9b-4399-aae0-1b99322816ce)
|
||||
)
|
||||
(wire (pts (xy 49.53 63.5) (xy 49.53 71.12))
|
||||
(stroke (width 0) (type default) (color 0 0 0 0))
|
||||
(uuid df55dc38-4eea-45b7-a8f8-143ff8efc8db)
|
||||
)
|
||||
(wire (pts (xy 96.52 63.5) (xy 96.52 73.66))
|
||||
(stroke (width 0) (type default) (color 0 0 0 0))
|
||||
(uuid f6b28b27-dfbc-4a27-bd69-3846a4360743)
|
||||
)
|
||||
|
||||
(symbol (lib_id "pspice:0") (at 110.49 91.44 0) (unit 1)
|
||||
(in_bom yes) (on_board yes) (fields_autoplaced)
|
||||
(uuid 1a5be67d-9866-401d-b629-c1e5f0845d67)
|
||||
(property "Reference" "#GND?" (id 0) (at 110.49 93.98 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(property "Value" "0" (id 1) (at 110.49 88.9 0))
|
||||
(property "Footprint" "" (id 2) (at 110.49 91.44 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(property "Datasheet" "~" (id 3) (at 110.49 91.44 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(pin "1" (uuid af973b92-8147-4b47-8721-90b66e63bbe1))
|
||||
)
|
||||
|
||||
(symbol (lib_id "Device:R") (at 110.49 77.47 180) (unit 1)
|
||||
(in_bom yes) (on_board yes) (fields_autoplaced)
|
||||
(uuid 32a7603d-e2c3-4e8d-ac2e-a18bb24f71aa)
|
||||
(property "Reference" "R2" (id 0) (at 113.03 76.1999 0)
|
||||
(effects (font (size 1.27 1.27)) (justify right))
|
||||
)
|
||||
(property "Value" "10k" (id 1) (at 113.03 78.7399 0)
|
||||
(effects (font (size 1.27 1.27)) (justify right))
|
||||
)
|
||||
(property "Footprint" "" (id 2) (at 112.268 77.47 90)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(property "Datasheet" "~" (id 3) (at 110.49 77.47 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(pin "1" (uuid c720522c-2ba3-466b-b6fd-5f98646ffa63))
|
||||
(pin "2" (uuid 232c161c-09f2-4e91-85fb-1f5d5b2879e9))
|
||||
)
|
||||
|
||||
(symbol (lib_id "Simulation_SPICE:VPULSE") (at 49.53 76.2 0) (unit 1)
|
||||
(in_bom yes) (on_board yes) (fields_autoplaced)
|
||||
(uuid 374e384d-7485-4232-8741-607d5a41e745)
|
||||
(property "Reference" "V1" (id 0) (at 53.34 73.4701 0)
|
||||
(effects (font (size 1.27 1.27)) (justify left))
|
||||
)
|
||||
(property "Value" "VPULSE" (id 1) (at 53.34 76.0101 0)
|
||||
(effects (font (size 1.27 1.27)) (justify left))
|
||||
)
|
||||
(property "Footprint" "" (id 2) (at 49.53 76.2 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(property "Datasheet" "~" (id 3) (at 49.53 76.2 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(property "Spice_Netlist_Enabled" "Y" (id 4) (at 49.53 76.2 0)
|
||||
(effects (font (size 1.27 1.27)) (justify left) hide)
|
||||
)
|
||||
(property "Spice_Primitive" "V" (id 5) (at 49.53 76.2 0)
|
||||
(effects (font (size 1.27 1.27)) (justify left) hide)
|
||||
)
|
||||
(property "Spice_Model" "dc 0 pulse(0 2 1m 50n 50n 1m 2m)" (id 6) (at 53.34 78.5501 0)
|
||||
(effects (font (size 1.27 1.27)) (justify left))
|
||||
)
|
||||
(pin "1" (uuid a7947fd2-165d-493f-b8e6-e78b75dfae94))
|
||||
(pin "2" (uuid 5a395677-a9eb-4147-bea3-fd3e5d82083c))
|
||||
)
|
||||
|
||||
(symbol (lib_id "Device:R") (at 72.39 63.5 90) (unit 1)
|
||||
(in_bom yes) (on_board yes) (fields_autoplaced)
|
||||
(uuid 7a95e03e-5b98-4b61-ab70-bbeb1cb67ed1)
|
||||
(property "Reference" "R1" (id 0) (at 72.39 57.15 90))
|
||||
(property "Value" "1k" (id 1) (at 72.39 59.69 90))
|
||||
(property "Footprint" "" (id 2) (at 72.39 65.278 90)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(property "Datasheet" "~" (id 3) (at 72.39 63.5 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(pin "1" (uuid 2eab2dfb-1a4b-401a-ac8e-8b70039fa135))
|
||||
(pin "2" (uuid e4424596-4abb-4814-957e-e352746501fa))
|
||||
)
|
||||
|
||||
(symbol (lib_id "Device:D") (at 96.52 77.47 90) (unit 1)
|
||||
(in_bom yes) (on_board yes) (fields_autoplaced)
|
||||
(uuid 828fa253-b44e-4f6e-a95a-66db5e9fea1d)
|
||||
(property "Reference" "D1" (id 0) (at 99.06 76.1999 90)
|
||||
(effects (font (size 1.27 1.27)) (justify right))
|
||||
)
|
||||
(property "Value" "D" (id 1) (at 99.06 78.7399 90)
|
||||
(effects (font (size 1.27 1.27)) (justify right))
|
||||
)
|
||||
(property "Footprint" "" (id 2) (at 96.52 77.47 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(property "Datasheet" "~" (id 3) (at 96.52 77.47 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(property "Spice_Primitive" "D" (id 4) (at 96.52 77.47 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(property "Spice_Model" "1N456" (id 5) (at 96.52 77.47 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(property "Spice_Netlist_Enabled" "Y" (id 6) (at 96.52 77.47 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(property "Spice_Lib_File" "issue13591_models\\diode.lib" (id 7) (at 96.52 77.47 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(property "Spice_Node_Sequence" "2 1" (id 8) (at 96.52 77.47 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(pin "1" (uuid aee777e6-7ff9-4ad6-b577-bdc81dc1193f))
|
||||
(pin "2" (uuid bd555bb7-3705-46ea-83aa-fec188339f87))
|
||||
)
|
||||
|
||||
(symbol (lib_id "pspice:0") (at 49.53 91.44 0) (unit 1)
|
||||
(in_bom yes) (on_board yes) (fields_autoplaced)
|
||||
(uuid 953baf45-76c0-417d-b68a-33fecdb25a10)
|
||||
(property "Reference" "#GND01" (id 0) (at 49.53 93.98 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(property "Value" "0" (id 1) (at 49.53 88.9 0))
|
||||
(property "Footprint" "" (id 2) (at 49.53 91.44 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(property "Datasheet" "~" (id 3) (at 49.53 91.44 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(pin "1" (uuid 77e096c3-94c7-4388-beca-f23c80794d4d))
|
||||
)
|
||||
|
||||
(symbol (lib_id "pspice:0") (at 96.52 91.44 0) (unit 1)
|
||||
(in_bom yes) (on_board yes) (fields_autoplaced)
|
||||
(uuid e743f90c-f4b3-4e96-b93e-fa4a32eee11e)
|
||||
(property "Reference" "#GND02" (id 0) (at 96.52 93.98 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(property "Value" "0" (id 1) (at 96.52 88.9 0))
|
||||
(property "Footprint" "" (id 2) (at 96.52 91.44 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(property "Datasheet" "~" (id 3) (at 96.52 91.44 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(pin "1" (uuid 8e93e08f-211b-4f8d-bccf-f7d4fc979e9a))
|
||||
)
|
||||
|
||||
(sheet_instances
|
||||
(path "/" (page "1"))
|
||||
)
|
||||
|
||||
(symbol_instances
|
||||
(path "/953baf45-76c0-417d-b68a-33fecdb25a10"
|
||||
(reference "#GND01") (unit 1) (value "0") (footprint "")
|
||||
)
|
||||
(path "/e743f90c-f4b3-4e96-b93e-fa4a32eee11e"
|
||||
(reference "#GND02") (unit 1) (value "0") (footprint "")
|
||||
)
|
||||
(path "/1a5be67d-9866-401d-b629-c1e5f0845d67"
|
||||
(reference "#GND?") (unit 1) (value "0") (footprint "")
|
||||
)
|
||||
(path "/828fa253-b44e-4f6e-a95a-66db5e9fea1d"
|
||||
(reference "D1") (unit 1) (value "D") (footprint "")
|
||||
)
|
||||
(path "/7a95e03e-5b98-4b61-ab70-bbeb1cb67ed1"
|
||||
(reference "R1") (unit 1) (value "1k") (footprint "")
|
||||
)
|
||||
(path "/32a7603d-e2c3-4e8d-ac2e-a18bb24f71aa"
|
||||
(reference "R2") (unit 1) (value "10k") (footprint "")
|
||||
)
|
||||
(path "/374e384d-7485-4232-8741-607d5a41e745"
|
||||
(reference "V1") (unit 1) (value "VPULSE") (footprint "")
|
||||
)
|
||||
)
|
||||
)
|
|
@ -0,0 +1,10 @@
|
|||
KiCad schematic
|
||||
.include "/Users/jeff/kicad_arm/kicad/qa/data/eeschema/issue13591_models/diode.lib"
|
||||
.save all
|
||||
.probe alli
|
||||
.tran 1us 1ms
|
||||
R2 0 Net-_D1-A_ 10k
|
||||
D1 Net-_D1-A_ 0 1N456
|
||||
R1 Net-_R1-Pad1_ Net-_D1-A_ 1k
|
||||
V1 Net-_R1-Pad1_ 0 dc 0 pulse(0 2 1m 50n 50n 1m 2m)
|
||||
.end
|
|
@ -0,0 +1,22 @@
|
|||
*****
|
||||
* DIODE.LIB
|
||||
* spectrum
|
||||
* andy
|
||||
* Generated by the Micro-Cap Model program Version 11.0.1.7.
|
||||
*****
|
||||
|
||||
*** Low Leakage Diode
|
||||
.MODEL 1N456 D (BV=30 CJO=4.505p IBV=100p IS=29.054p M=385.099m N=1.425
|
||||
+ RL=125.018MEG RS=910.713m TT=5u VJ=700m)
|
||||
|
||||
*** Low Leakage Diode
|
||||
.MODEL 1N456A D (BV=30 CJO=4.505E-12 IBV=100E-12 IS=29.054E-12 M=385.099E-3 N=1.425
|
||||
+ RS=910.713E-3 TT=5E-6 VJ=700E-3)
|
||||
|
||||
*** Low Leakage Diode
|
||||
.MODEL 1N457 D (BV=70 CJO=4.505p IBV=100p IS=19.191p M=385.099m N=1.388
|
||||
+ RL=125.012MEG RS=980.164m TT=5u VJ=700m)
|
||||
|
||||
*** Low Leakage Diode
|
||||
.MODEL 1N457A D (BV=70 CJO=4.505p IBV=100p IS=19.191p M=385.099m N=1.388
|
||||
+ RL=125.018MEG RS=980.164m TT=5u VJ=700m)
|
|
@ -96,6 +96,7 @@ if( KICAD_SPICE )
|
|||
sim/test_library_spice.cpp
|
||||
sim/test_sim_model_inference.cpp
|
||||
sim/test_sim_model_ngspice.cpp
|
||||
sim/test_sim_regressions.cpp
|
||||
sim/test_ngspice_helpers.cpp
|
||||
)
|
||||
endif()
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2023 KiCad Developers, see AUTHORS.TXT for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifdef KICAD_SPICE
|
||||
|
||||
#include <qa_utils/wx_utils/unit_test_utils.h>
|
||||
#include <boost/test/results_collector.hpp> // To check if the current test failed (to be moved?).
|
||||
#include <eeschema_test_utils.h>
|
||||
#include <test_netlist_exporter_spice.h>
|
||||
#include <wx/ffile.h>
|
||||
#include <mock_pgm_base.h>
|
||||
#include <locale_io.h>
|
||||
|
||||
|
||||
class TEST_SIM_REGRESSIONS_FIXTURE : public TEST_NETLIST_EXPORTER_SPICE_FIXTURE
|
||||
{
|
||||
public:
|
||||
TEST_SIM_REGRESSIONS_FIXTURE() :
|
||||
TEST_NETLIST_EXPORTER_SPICE_FIXTURE()
|
||||
{
|
||||
}
|
||||
|
||||
~TEST_SIM_REGRESSIONS_FIXTURE()
|
||||
{
|
||||
}
|
||||
|
||||
wxFileName GetSchematicPath( const wxString& aBaseName ) override
|
||||
{
|
||||
wxFileName fn = KI_TEST::GetEeschemaTestDataDir();
|
||||
fn.SetName( aBaseName );
|
||||
fn.SetExt( KiCadSchematicFileExtension );
|
||||
|
||||
return fn;
|
||||
}
|
||||
|
||||
wxString GetNetlistPath( bool aTest = false ) override
|
||||
{
|
||||
wxFileName netFile = m_schematic.Prj().GetProjectFullName();
|
||||
|
||||
if( aTest )
|
||||
netFile.SetName( netFile.GetName() + "_test" );
|
||||
|
||||
netFile.SetExt( "spice" );
|
||||
return netFile.GetFullPath();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
BOOST_FIXTURE_TEST_SUITE( SimRegressions, TEST_SIM_REGRESSIONS_FIXTURE )
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE( WindowsPaths )
|
||||
{
|
||||
LOCALE_IO dummy;
|
||||
|
||||
TestNetlist( "issue13591" );
|
||||
TestTranPoint( 100e-6, { { "I(R1)", 0 }, { "I(R2)", 0 } } );
|
||||
TestTranPoint( 500e-6, { { "I(R1)", 0 }, { "I(R2)", 0 } } );
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
#endif // KICAD_SPICE
|
|
@ -25,263 +25,12 @@
|
|||
|
||||
#include <qa_utils/wx_utils/unit_test_utils.h>
|
||||
#include <boost/test/results_collector.hpp> // To check if the current test failed (to be moved?).
|
||||
#include <eeschema_test_utils.h>
|
||||
#include <netlist_exporter_spice.h>
|
||||
#include <sim/ngspice.h>
|
||||
#include <test_netlist_exporter_spice.h>
|
||||
#include <sim/spice_reporter.h>
|
||||
#include <wx/ffile.h>
|
||||
#include <mock_pgm_base.h>
|
||||
#include <locale_io.h>
|
||||
|
||||
|
||||
class TEST_NETLIST_EXPORTER_SPICE_FIXTURE : public TEST_NETLIST_EXPORTER_FIXTURE<NETLIST_EXPORTER_SPICE>
|
||||
{
|
||||
public:
|
||||
class SPICE_TEST_REPORTER : public SPICE_REPORTER
|
||||
{
|
||||
public:
|
||||
SPICE_TEST_REPORTER( std::shared_ptr<wxString> aLog ) : m_log( std::move( aLog ) ) {}
|
||||
|
||||
REPORTER& Report( const wxString& aText,
|
||||
SEVERITY aSeverity = RPT_SEVERITY_UNDEFINED ) override
|
||||
{
|
||||
*m_log << aText << "\n";
|
||||
|
||||
// You can add a debug trace here.
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool HasMessage() const override { return false; }
|
||||
|
||||
void OnSimStateChange( SPICE_SIMULATOR* aObject, SIM_STATE aNewState ) override
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<wxString> m_log;
|
||||
};
|
||||
|
||||
TEST_NETLIST_EXPORTER_SPICE_FIXTURE() :
|
||||
TEST_NETLIST_EXPORTER_FIXTURE<NETLIST_EXPORTER_SPICE>(),
|
||||
m_simulator( SPICE_SIMULATOR::CreateInstance( "ngspice" ) ),
|
||||
m_log( std::make_shared<wxString>() ),
|
||||
m_reporter( std::make_unique<SPICE_TEST_REPORTER>( m_log ) ),
|
||||
m_abort( false )
|
||||
{
|
||||
}
|
||||
|
||||
~TEST_NETLIST_EXPORTER_SPICE_FIXTURE()
|
||||
{
|
||||
using namespace boost::unit_test;
|
||||
|
||||
test_case::id_t id = framework::current_test_case().p_id;
|
||||
test_results results = results_collector.results( id );
|
||||
|
||||
// Output a log if the test has failed.
|
||||
BOOST_CHECK_MESSAGE( results.passed(), "\nNGSPICE LOG\n===========\n" << *m_log );
|
||||
}
|
||||
|
||||
wxFileName GetSchematicPath( const wxString& aBaseName ) override
|
||||
{
|
||||
wxFileName fn = KI_TEST::GetEeschemaTestDataDir();
|
||||
fn.AppendDir( "spice_netlists" );
|
||||
fn.AppendDir( aBaseName );
|
||||
fn.SetName( aBaseName );
|
||||
fn.SetExt( KiCadSchematicFileExtension );
|
||||
|
||||
return fn;
|
||||
}
|
||||
|
||||
wxString GetNetlistPath( bool aTest = false ) override
|
||||
{
|
||||
wxFileName netFile = m_schematic.Prj().GetProjectFullName();
|
||||
|
||||
if( aTest )
|
||||
netFile.SetName( netFile.GetName() + "_test" );
|
||||
|
||||
netFile.SetExt( "spice" );
|
||||
return netFile.GetFullPath();
|
||||
}
|
||||
|
||||
void CompareNetlists() override
|
||||
{
|
||||
m_abort = false;
|
||||
|
||||
// Our simulator is actually Ngspice.
|
||||
NGSPICE* ngspice = dynamic_cast<NGSPICE*>( m_simulator.get() );
|
||||
BOOST_REQUIRE( ngspice );
|
||||
|
||||
ngspice->SetReporter( m_reporter.get() );
|
||||
|
||||
wxFFile file( GetNetlistPath( true ), "rt" );
|
||||
wxString netlist;
|
||||
|
||||
file.ReadAll( &netlist );
|
||||
|
||||
//ngspice->Init();
|
||||
ngspice->Command( "set ngbehavior=ps" );
|
||||
ngspice->Command( "setseed 1" );
|
||||
BOOST_REQUIRE( ngspice->LoadNetlist( std::string( netlist.ToUTF8() ) ) );
|
||||
BOOST_REQUIRE( ngspice->Run() );
|
||||
|
||||
// Test if ngspice cannot run a simulation (missing code models).
|
||||
// in this case the log contains "MIF-ERROR" and/or "Error: circuit not parsed"
|
||||
// when the simulation is not run the spice command "linearize" crashes.
|
||||
bool err_found = m_log->Find( wxT( "Error: circuit not parsed" ) ) != wxNOT_FOUND
|
||||
|| m_log->Find( wxT( "MIF-ERROR" ) ) != wxNOT_FOUND;
|
||||
|
||||
if( err_found )
|
||||
{
|
||||
if( m_log->Find( wxT( "MIF-ERROR" ) ) != wxNOT_FOUND )
|
||||
wxLogWarning( wxT( "Cannot run ngspice. test skipped. Missing code model files?" ) );
|
||||
else
|
||||
wxLogWarning( wxT( "Cannot run ngspice. test skipped. Install error?" ) );
|
||||
|
||||
m_abort = true;
|
||||
|
||||
// Still display the original netlist in this case.
|
||||
*m_log << "Original Netlist\n";
|
||||
*m_log << "----------------\n";
|
||||
*m_log << netlist << "\n";
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// We need to make sure that the number of points always the same.
|
||||
ngspice->Command( "linearize" );
|
||||
|
||||
|
||||
// Debug info.
|
||||
|
||||
// Display all vectors.
|
||||
ngspice->Command( "echo Available Vectors" );
|
||||
ngspice->Command( "echo -----------------" );
|
||||
ngspice->Command( "display" );
|
||||
|
||||
// Display the original netlist.
|
||||
*m_log << "Original Netlist\n";
|
||||
*m_log << "----------------\n";
|
||||
*m_log << netlist << "\n";
|
||||
|
||||
// Display the expanded netlist.
|
||||
ngspice->Command( "echo Expanded Netlist" );
|
||||
ngspice->Command( "echo ----------------" );
|
||||
ngspice->Command( "listing runnable" );
|
||||
}
|
||||
|
||||
void TestNetlist( const wxString& aBaseName )
|
||||
{
|
||||
// We actually ended up only generating the netlist here.
|
||||
TEST_NETLIST_EXPORTER_FIXTURE<NETLIST_EXPORTER_SPICE>::TestNetlist( aBaseName );
|
||||
}
|
||||
|
||||
void TestOpPoint( double aRefValue, const std::string& aVectorName, double aMaxRelError = 1e-2 )
|
||||
{
|
||||
BOOST_TEST_CONTEXT( "Vector name: " << aVectorName )
|
||||
{
|
||||
NGSPICE* ngspice = static_cast<NGSPICE*>( m_simulator.get() );
|
||||
|
||||
std::vector<double> vector = ngspice->GetRealPlot( aVectorName );
|
||||
|
||||
BOOST_REQUIRE_EQUAL( vector.size(), 1 );
|
||||
|
||||
double maxError = abs( aRefValue * aMaxRelError );
|
||||
BOOST_CHECK_LE( abs( vector[0] - aRefValue ), aMaxRelError );
|
||||
}
|
||||
}
|
||||
|
||||
void TestPoint( const std::string& aXVectorName, double aXValue,
|
||||
const std::map<const std::string, double> aTestVectorsAndValues,
|
||||
double aMaxRelError = 1e-2 )
|
||||
{
|
||||
// The default aMaxRelError is fairly large because we have some problems with determinism
|
||||
// in QA pipeline. We don't need to fix this for now because, if this has to be fixed in
|
||||
// the first place, this has to be done from Ngspice's side.
|
||||
|
||||
BOOST_TEST_CONTEXT( "X vector name: " << aXVectorName << ", X value: " << aXValue )
|
||||
{
|
||||
NGSPICE* ngspice = static_cast<NGSPICE*>( m_simulator.get() );
|
||||
|
||||
std::vector<double> xVector = ngspice->GetRealPlot( aXVectorName );
|
||||
std::size_t i = 0;
|
||||
|
||||
for(; i < xVector.size(); ++i )
|
||||
{
|
||||
double inf = std::numeric_limits<double>::infinity();
|
||||
|
||||
double leftDelta = ( aXValue - ( i >= 1 ? xVector[i - 1] : -inf ) );
|
||||
double middleDelta = ( aXValue - xVector[i] );
|
||||
double rightDelta = ( aXValue - ( i < xVector.size() - 1 ? xVector[i + 1] : inf ) );
|
||||
|
||||
// Check if this point is the closest one.
|
||||
if( abs( middleDelta ) <= abs( leftDelta )
|
||||
&& abs( middleDelta ) <= abs( rightDelta ) )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_REQUIRE_LT( i, xVector.size() );
|
||||
|
||||
for( auto& [vectorName, refValue] : aTestVectorsAndValues )
|
||||
{
|
||||
std::vector<double> yVector = ngspice->GetMagPlot( vectorName );
|
||||
|
||||
BOOST_REQUIRE_GE( yVector.size(), i + 1 );
|
||||
|
||||
BOOST_TEST_CONTEXT( "Y vector name: " << vectorName
|
||||
<< ", Ref value: " << refValue
|
||||
<< ", Actual value: " << yVector[i] )
|
||||
{
|
||||
double maxError = abs( refValue * aMaxRelError );
|
||||
if( maxError == 0 )
|
||||
{
|
||||
// If refValue is 0, we need a obtain the max. error differently.
|
||||
maxError = aMaxRelError;
|
||||
}
|
||||
|
||||
BOOST_CHECK_LE( abs( yVector[i] - refValue ), maxError );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TestTranPoint( double aTime,
|
||||
const std::map<const std::string, double> aTestVectorsAndValues,
|
||||
double aMaxRelError = 1e-2 )
|
||||
{
|
||||
TestPoint( "time", aTime, aTestVectorsAndValues, aMaxRelError );
|
||||
}
|
||||
|
||||
void TestACPoint( double aFrequency,
|
||||
const std::map<const std::string, double> aTestVectorsAndValues,
|
||||
double aMaxRelError = 1e-2 )
|
||||
{
|
||||
TestPoint( "frequency", aFrequency, aTestVectorsAndValues, aMaxRelError );
|
||||
}
|
||||
|
||||
wxString GetResultsPath( bool aTest = false )
|
||||
{
|
||||
wxFileName netlistPath( GetNetlistPath( aTest ) );
|
||||
netlistPath.SetExt( "csv" );
|
||||
|
||||
return netlistPath.GetFullPath();
|
||||
}
|
||||
|
||||
unsigned GetNetlistOptions() override
|
||||
{
|
||||
return NETLIST_EXPORTER_SPICE::OPTION_SAVE_ALL_VOLTAGES
|
||||
| NETLIST_EXPORTER_SPICE::OPTION_SAVE_ALL_CURRENTS
|
||||
| NETLIST_EXPORTER_SPICE::OPTION_ADJUST_INCLUDE_PATHS
|
||||
| NETLIST_EXPORTER_SPICE::OPTION_SIM_COMMAND;
|
||||
}
|
||||
|
||||
std::shared_ptr<SPICE_SIMULATOR> m_simulator;
|
||||
std::shared_ptr<wxString> m_log;
|
||||
std::unique_ptr<SPICE_TEST_REPORTER> m_reporter;
|
||||
bool m_abort; // set to true to force abort durint a test
|
||||
};
|
||||
|
||||
|
||||
BOOST_FIXTURE_TEST_SUITE( NetlistExporterSpice, TEST_NETLIST_EXPORTER_SPICE_FIXTURE )
|
||||
|
||||
|
|
|
@ -0,0 +1,280 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2022 KiCad Developers, see AUTHORS.TXT for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifdef KICAD_SPICE
|
||||
|
||||
#include <qa_utils/wx_utils/unit_test_utils.h>
|
||||
#include <boost/test/results_collector.hpp> // To check if the current test failed (to be moved?).
|
||||
#include <eeschema_test_utils.h>
|
||||
#include <netlist_exporter_spice.h>
|
||||
#include <sim/ngspice.h>
|
||||
#include <sim/spice_reporter.h>
|
||||
#include <wx/ffile.h>
|
||||
#include <mock_pgm_base.h>
|
||||
#include <locale_io.h>
|
||||
|
||||
|
||||
class TEST_NETLIST_EXPORTER_SPICE_FIXTURE : public TEST_NETLIST_EXPORTER_FIXTURE<NETLIST_EXPORTER_SPICE>
|
||||
{
|
||||
public:
|
||||
class SPICE_TEST_REPORTER : public SPICE_REPORTER
|
||||
{
|
||||
public:
|
||||
SPICE_TEST_REPORTER( std::shared_ptr<wxString> aLog ) :
|
||||
m_log( std::move( aLog ) )
|
||||
{}
|
||||
|
||||
REPORTER& Report( const wxString& aText,
|
||||
SEVERITY aSeverity = RPT_SEVERITY_UNDEFINED ) override
|
||||
{
|
||||
*m_log << aText << "\n";
|
||||
|
||||
// You can add a debug trace here.
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool HasMessage() const override { return false; }
|
||||
|
||||
void OnSimStateChange( SPICE_SIMULATOR* aObject, SIM_STATE aNewState ) override { }
|
||||
|
||||
private:
|
||||
std::shared_ptr<wxString> m_log;
|
||||
};
|
||||
|
||||
TEST_NETLIST_EXPORTER_SPICE_FIXTURE() :
|
||||
TEST_NETLIST_EXPORTER_FIXTURE<NETLIST_EXPORTER_SPICE>(),
|
||||
m_simulator( SPICE_SIMULATOR::CreateInstance( "ngspice" ) ),
|
||||
m_log( std::make_shared<wxString>() ),
|
||||
m_reporter( std::make_unique<SPICE_TEST_REPORTER>( m_log ) ),
|
||||
m_abort( false )
|
||||
{
|
||||
}
|
||||
|
||||
~TEST_NETLIST_EXPORTER_SPICE_FIXTURE()
|
||||
{
|
||||
using namespace boost::unit_test;
|
||||
|
||||
test_case::id_t id = framework::current_test_case().p_id;
|
||||
test_results results = results_collector.results( id );
|
||||
|
||||
// Output a log if the test has failed.
|
||||
BOOST_CHECK_MESSAGE( results.passed(), "\nNGSPICE LOG\n===========\n" << *m_log );
|
||||
}
|
||||
|
||||
wxFileName GetSchematicPath( const wxString& aBaseName ) override
|
||||
{
|
||||
wxFileName fn = KI_TEST::GetEeschemaTestDataDir();
|
||||
fn.AppendDir( "spice_netlists" );
|
||||
fn.AppendDir( aBaseName );
|
||||
fn.SetName( aBaseName );
|
||||
fn.SetExt( KiCadSchematicFileExtension );
|
||||
|
||||
return fn;
|
||||
}
|
||||
|
||||
wxString GetNetlistPath( bool aTest = false ) override
|
||||
{
|
||||
wxFileName netFile = m_schematic.Prj().GetProjectFullName();
|
||||
|
||||
if( aTest )
|
||||
netFile.SetName( netFile.GetName() + "_test" );
|
||||
|
||||
netFile.SetExt( "spice" );
|
||||
return netFile.GetFullPath();
|
||||
}
|
||||
|
||||
void CompareNetlists() override
|
||||
{
|
||||
m_abort = false;
|
||||
|
||||
// Our simulator is actually Ngspice.
|
||||
NGSPICE* ngspice = dynamic_cast<NGSPICE*>( m_simulator.get() );
|
||||
BOOST_REQUIRE( ngspice );
|
||||
|
||||
ngspice->SetReporter( m_reporter.get() );
|
||||
|
||||
wxFFile file( GetNetlistPath( true ), "rt" );
|
||||
wxString netlist;
|
||||
|
||||
file.ReadAll( &netlist );
|
||||
|
||||
//ngspice->Init();
|
||||
ngspice->Command( "set ngbehavior=ps" );
|
||||
ngspice->Command( "setseed 1" );
|
||||
BOOST_REQUIRE( ngspice->LoadNetlist( std::string( netlist.ToUTF8() ) ) );
|
||||
BOOST_REQUIRE( ngspice->Run() );
|
||||
|
||||
// Test if ngspice cannot run a simulation (missing code models).
|
||||
// in this case the log contains "MIF-ERROR" and/or "Error: circuit not parsed"
|
||||
// when the simulation is not run the spice command "linearize" crashes.
|
||||
bool err_found = m_log->Find( wxT( "Error: circuit not parsed" ) ) != wxNOT_FOUND
|
||||
|| m_log->Find( wxT( "MIF-ERROR" ) ) != wxNOT_FOUND;
|
||||
|
||||
if( err_found )
|
||||
{
|
||||
if( m_log->Find( wxT( "MIF-ERROR" ) ) != wxNOT_FOUND )
|
||||
wxLogWarning( wxT( "Cannot run ngspice. test skipped. Missing code model files?" ) );
|
||||
else
|
||||
wxLogWarning( wxT( "Cannot run ngspice. test skipped. Install error?" ) );
|
||||
|
||||
m_abort = true;
|
||||
|
||||
// Still display the original netlist in this case.
|
||||
*m_log << "Original Netlist\n";
|
||||
*m_log << "----------------\n";
|
||||
*m_log << netlist << "\n";
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// We need to make sure that the number of points always the same.
|
||||
ngspice->Command( "linearize" );
|
||||
|
||||
|
||||
// Debug info.
|
||||
|
||||
// Display all vectors.
|
||||
ngspice->Command( "echo Available Vectors" );
|
||||
ngspice->Command( "echo -----------------" );
|
||||
ngspice->Command( "display" );
|
||||
|
||||
// Display the original netlist.
|
||||
*m_log << "Original Netlist\n";
|
||||
*m_log << "----------------\n";
|
||||
*m_log << netlist << "\n";
|
||||
|
||||
// Display the expanded netlist.
|
||||
ngspice->Command( "echo Expanded Netlist" );
|
||||
ngspice->Command( "echo ----------------" );
|
||||
ngspice->Command( "listing runnable" );
|
||||
}
|
||||
|
||||
void TestOpPoint( double aRefValue, const std::string& aVectorName, double aMaxRelError = 1e-2 )
|
||||
{
|
||||
BOOST_TEST_CONTEXT( "Vector name: " << aVectorName )
|
||||
{
|
||||
NGSPICE* ngspice = static_cast<NGSPICE*>( m_simulator.get() );
|
||||
|
||||
std::vector<double> vector = ngspice->GetRealPlot( aVectorName );
|
||||
|
||||
BOOST_REQUIRE_EQUAL( vector.size(), 1 );
|
||||
|
||||
double maxError = abs( aRefValue * aMaxRelError );
|
||||
BOOST_CHECK_LE( abs( vector[0] - aRefValue ), aMaxRelError );
|
||||
}
|
||||
}
|
||||
|
||||
void TestPoint( const std::string& aXVectorName, double aXValue,
|
||||
const std::map<const std::string, double> aTestVectorsAndValues,
|
||||
double aMaxRelError = 1e-2 )
|
||||
{
|
||||
// The default aMaxRelError is fairly large because we have some problems with determinism
|
||||
// in QA pipeline. We don't need to fix this for now because, if this has to be fixed in
|
||||
// the first place, this has to be done from Ngspice's side.
|
||||
|
||||
BOOST_TEST_CONTEXT( "X vector name: " << aXVectorName << ", X value: " << aXValue )
|
||||
{
|
||||
NGSPICE* ngspice = static_cast<NGSPICE*>( m_simulator.get() );
|
||||
|
||||
std::vector<double> xVector = ngspice->GetRealPlot( aXVectorName );
|
||||
std::size_t i = 0;
|
||||
|
||||
for(; i < xVector.size(); ++i )
|
||||
{
|
||||
double inf = std::numeric_limits<double>::infinity();
|
||||
|
||||
double leftDelta = ( aXValue - ( i >= 1 ? xVector[i - 1] : -inf ) );
|
||||
double middleDelta = ( aXValue - xVector[i] );
|
||||
double rightDelta = ( aXValue - ( i < xVector.size() - 1 ? xVector[i + 1] : inf ) );
|
||||
|
||||
// Check if this point is the closest one.
|
||||
if( abs( middleDelta ) <= abs( leftDelta )
|
||||
&& abs( middleDelta ) <= abs( rightDelta ) )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_REQUIRE_LT( i, xVector.size() );
|
||||
|
||||
for( auto& [vectorName, refValue] : aTestVectorsAndValues )
|
||||
{
|
||||
std::vector<double> yVector = ngspice->GetMagPlot( vectorName );
|
||||
|
||||
BOOST_REQUIRE_GE( yVector.size(), i + 1 );
|
||||
|
||||
BOOST_TEST_CONTEXT( "Y vector name: " << vectorName
|
||||
<< ", Ref value: " << refValue
|
||||
<< ", Actual value: " << yVector[i] )
|
||||
{
|
||||
double maxError = abs( refValue * aMaxRelError );
|
||||
if( maxError == 0 )
|
||||
{
|
||||
// If refValue is 0, we need a obtain the max. error differently.
|
||||
maxError = aMaxRelError;
|
||||
}
|
||||
|
||||
BOOST_CHECK_LE( abs( yVector[i] - refValue ), maxError );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TestTranPoint( double aTime,
|
||||
const std::map<const std::string, double> aTestVectorsAndValues,
|
||||
double aMaxRelError = 1e-2 )
|
||||
{
|
||||
TestPoint( "time", aTime, aTestVectorsAndValues, aMaxRelError );
|
||||
}
|
||||
|
||||
void TestACPoint( double aFrequency,
|
||||
const std::map<const std::string, double> aTestVectorsAndValues,
|
||||
double aMaxRelError = 1e-2 )
|
||||
{
|
||||
TestPoint( "frequency", aFrequency, aTestVectorsAndValues, aMaxRelError );
|
||||
}
|
||||
|
||||
wxString GetResultsPath( bool aTest = false )
|
||||
{
|
||||
wxFileName netlistPath( GetNetlistPath( aTest ) );
|
||||
netlistPath.SetExt( "csv" );
|
||||
|
||||
return netlistPath.GetFullPath();
|
||||
}
|
||||
|
||||
unsigned GetNetlistOptions() override
|
||||
{
|
||||
return NETLIST_EXPORTER_SPICE::OPTION_SAVE_ALL_VOLTAGES
|
||||
| NETLIST_EXPORTER_SPICE::OPTION_SAVE_ALL_CURRENTS
|
||||
| NETLIST_EXPORTER_SPICE::OPTION_ADJUST_INCLUDE_PATHS
|
||||
| NETLIST_EXPORTER_SPICE::OPTION_SIM_COMMAND;
|
||||
}
|
||||
|
||||
std::shared_ptr<SPICE_SIMULATOR> m_simulator;
|
||||
std::shared_ptr<wxString> m_log;
|
||||
std::unique_ptr<SPICE_TEST_REPORTER> m_reporter;
|
||||
bool m_abort; // set to true to force abort durint a test
|
||||
};
|
||||
|
||||
|
||||
#endif // KICAD_SPICE
|
Loading…
Reference in New Issue