def main(): parser = argparse.ArgumentParser(description='Convert a circuit file to PySpice') parser.add_argument('circuit_file', # metavar='circuit_file', help='.cir file') parser.add_argument('-o', '--output', default=None, help='Output file') parser.add_argument('--ground', type=int, default=0, help='Ground node') parser.add_argument('--build', default=False, action='store_true', help='Build circuit') args = parser.parse_args() ############################################## parser = SpiceParser(path=args.circuit_file) if args.build: parser.build_circuit() circuit = parser.to_python_code(ground=args.ground) if args.output is not None: with open(args.output, 'w') as f: f.write(circuit) else: print(circuit)
def main(): # Monkeypatch the exec_command() to not bail if it detects an 'error' in stderr, # these 'errors' don't seem to actually prevent the sim from working correctly Shared.NgSpiceShared.exec_command = exec_command libraries_path = find_libraries() spice_library = SpiceLibrary(libraries_path) directory_path = Path(__file__).resolve().parent kicad_netlist_path = directory_path.joinpath( 'wien-bridge-oscillator-sim.cir') parser = SpiceParser(path=str(kicad_netlist_path)) circuit = parser.build_circuit(ground=0) simulator = circuit.simulator(temperature=25, nominal_temperature=25) analysis = simulator.transient(step_time=10 @ u_us, end_time=60 @ u_ms) v_sine_out = analysis['SINE_OUT'] first_index_of_interest = np.where( v_sine_out.abscissa.as_ndarray() > 0.04)[0][0] fig, ax = plt.subplots(1, figsize=(10, 5)) ax.plot(v_sine_out.abscissa.as_ndarray()[first_index_of_interest:], v_sine_out.as_ndarray()[first_index_of_interest:]) ax.legend(('SINE_OUT', ), loc=(.8, .8)) ax.grid() ax.set_xlabel('Time (s)') ax.set_ylabel('Voltage (V)') plt.tight_layout() plt.savefig('v-sine-out.png')
def main(): # Monkeypatch the exec_command() to not bail if it detects an 'error' in stderr, # these 'errors' don't seem to actually prevent the sim from working correctly Shared.NgSpiceShared.exec_command = exec_command libraries_path = find_libraries() spice_library = SpiceLibrary(libraries_path) directory_path = Path(__file__).resolve().parent kicad_netlist_path = directory_path.joinpath('simulation.cir') netlist_without_quotes_path = Path('./simulation-without-quotes.cir') remove_include_quotes(kicad_netlist_path, netlist_without_quotes_path) parser = SpiceParser(path=str(netlist_without_quotes_path)) circuit = parser.build_circuit(ground=0) simulator = circuit.simulator(temperature=25, nominal_temperature=25) analysis = simulator.transient(step_time=100 @ u_ps, end_time=100 @ u_ns) v_out = analysis['OUT'] fig, ax = plt.subplots(1, figsize=(10, 5)) ax.plot(v_out.abscissa.as_ndarray() * 1e9, v_out.as_ndarray()) ax.legend(('OUT', ), loc=(.8, .8)) ax.grid() ax.set_xlabel('Time (ns)') ax.set_ylabel('Voltage (V)') plt.tight_layout() plt.savefig('out.png')
def parser_netlist(self): """ 解析netlist :return:self.circurt属性绑定解析的netlist电路 """ parser = SpiceParser(path=self._path) self.circuit = parser.build_circuit() print(str(self.circuit))
def circuit_gft(prb): circuit_file = SpiceParser(source=prb[0]) circuit = circuit_file.build_circuit() circuit.parameter('prb', str(prb[1])) # Fixme: simulate with Xyce, CI !!! simulator = circuit.simulator(simulator='xyce-serial') simulator.save(['all']) return simulator
def is_valid_netlist(textfile, name=None): try: parser = SpiceParser(source=textfile) circuit = parser.build_circuit() return len(circuit.elements) > 0 except: if name: print(f'invalid spice file: {name}', file=sys.stderr) return False
def main(): # Monkeypatch the exec_command() to not bail if it detects an 'error' in stderr, # these 'errors' don't seem to actually prevent the sim from working correctly Shared.NgSpiceShared.exec_command = exec_command libraries_path = find_libraries() spice_library = SpiceLibrary(libraries_path) directory_path = Path(__file__).resolve().parent kicad_netlist_path = directory_path.joinpath('schematic.cir') netlist_without_quotes_path = Path('./simulation-without-quotes.cir') remove_include_quotes(kicad_netlist_path, netlist_without_quotes_path) parser = SpiceParser(path=str(netlist_without_quotes_path)) circuit = parser.build_circuit(ground=0) simulator = circuit.simulator(temperature=25, nominal_temperature=25) # analysis = simulator.transient(step_time=100@u_us, end_time=1000@u_ms) analysis = simulator.ac(start_frequency=100@u_mHz, stop_frequency=10@u_kHz, number_of_points=50, variation='dec') v_out = analysis['v_out'] mag = 20*np.log10(np.abs(v_out.as_ndarray())) print(mag) freq = analysis.frequency.as_ndarray() r1_Ohms = 2e3 r2_Ohms = 10e3 ratio = r2_Ohms / (r1_Ohms + r2_Ohms) ratio_dB = 20*np.log10(ratio) ratio_dB = -1.75 r_parallel = (r1_Ohms * r2_Ohms) / (r1_Ohms + r2_Ohms) c_F = 10e-6 fc = 1 / (2*np.pi*r_parallel*c_F) print(ratio_dB) fig, ax = plt.subplots(1, figsize=(10, 7)) ax.plot(freq, mag, label='$V_{OUT}$') # ax.legend(('$V_{OUT}$',), loc=(.8,.8)) ax.grid() ax.set_xscale('log') ax.set_xlabel('Frequency (Hz)') ax.set_ylabel('Voltage Magnitude (dB)') ax.axvline(fc, color='C2', label='$f_c$') ax.axhline(ratio_dB, color='C1', label=f'{ratio_dB:.2f}dB (DC gain)') ax.axhline(ratio_dB - 3.0, color='C1', label=f'{ratio_dB - 3:.2f}dB (DC gain - 3dB)') ax.legend() plt.tight_layout() plt.savefig('out.png')
def fetch_graphs(files, min_edges=0): filenames = h.valid_netlist_sources(files) source = next(filenames) parser = SpiceParser(source=source) circuit = parser.build_circuit() (nodes, edges) = h.get_nodes_edges(circuit) # TODO: randomly remove one each time until it is empty graphs = [] while len(edges) > min_edges: graphs.append((nodes, edges)) (nodes, edges) = a.remove_random_node(nodes, edges) return graphs
def build_cgraph_lib(ffn_netlist, dir_graph_out=None, ground=0, remove_dummy=False, dir_node_edge_list=None, dir_lib_out=None, guess_by_name=True, add_edge_annotation=False): """ ffn_netlist: full file path of netlist to parse dir_graph_out: directory path to save the resulting circuit topology graph in yaml format dir_lib_out: directory path to save circuit topology graph lib in pickle format remove_dummy: when True, remove dummy mos guess_by_name: when True, some attributes such as signal type is inferred/guessed from net/instance name add_edge_annotation: when True, add matching/group edge constraints to the graph return dict (i.e. {circuit_name:networkx.Graph}) """ from PySpice.Spice.Parser import SpiceParser parser = SpiceParser(path=ffn_netlist) circuit = parser.build_circuit(ground=ground) cgraph_dict = {} top_name, ext = os.path.splitext(os.path.basename(ffn_netlist)) G = build_cgraph(circuit, top_name, guess_by_name=guess_by_name, add_edge_annotation=add_edge_annotation) cgraph_dict[top_name] = G for c in (circuit.subcircuits): for e in (c.elements): G = build_cgraph(c, c.name, guess_by_name=guess_by_name, add_edge_annotation=add_edge_annotation) cgraph_dict[c.name] = G for name, G in cgraph_dict.items(): if(dir_graph_out is not None): nx.write_yaml(G, os.path.join(dir_graph_out, "%s.yaml" % name)) if(dir_node_edge_list is not None): node_number = {} with open(os.path.join(dir_node_edge_list, "%s.nodelist" % name), 'w') as f: for ii, n in enumerate(G.nodes()): f.write("%s %d\n" % (n, ii)) node_number[n]=ii with open(os.path.join(dir_node_edge_list, "%s.edgelist" % name), 'w') as f: for e in G.edges(): f.write('%s %s\n' % (node_number[e[0]], node_number[e[1]])) if(dir_lib_out is not None): with open(os.path.join(dir_lib_out, "%s.cgraph.pkl" % top_name), 'wb') as f: pickle.dump(cgraph_dict, f, -1) return cgraph_dict
def main(): # Monkeypatch the exec_command() to not bail if it detects an 'error' in stderr, # these 'errors' don't seem to actually prevent the sim from working correctly Shared.NgSpiceShared.exec_command = exec_command libraries_path = find_libraries() spice_library = SpiceLibrary(libraries_path) directory_path = Path(__file__).resolve().parent kicad_netlist_path = directory_path.joinpath('schematic.cir') netlist_without_quotes_path = Path('./simulation-without-quotes.cir') remove_include_quotes(kicad_netlist_path, netlist_without_quotes_path) parser = SpiceParser(path=str(netlist_without_quotes_path)) circuit = parser.build_circuit(ground=0) simulator = circuit.simulator(temperature=25, nominal_temperature=25) analysis = simulator.transient(step_time=1 @ u_us, end_time=1000 @ u_us) # analysis = simulator.ac(start_frequency=100@u_mHz, stop_frequency=10@u_kHz, number_of_points=50, variation='dec') v_in = analysis['/v_in'] v_out = analysis['v_out'] fig, ax = plt.subplots(1, figsize=(7, 5)) ax.plot(v_in.abscissa.as_ndarray() * 1e6, v_in.as_ndarray(), label='$v_{in}$') ax.plot(v_out.abscissa.as_ndarray() * 1e6, v_out.as_ndarray(), label='$v_{out}$') ax.axhline(-5.0, ls='--', color='C0') ax.axhline(5.0, ls='--', color='C0') ax.axhline(0, ls='--', color='C1') ax.axhline(3.3, ls='--', color='C1') ax.grid() ax.set_xlabel('Time [us]') ax.set_ylabel('Voltage [V]') ax.legend() plt.tight_layout() plt.savefig('out.png')
def netlist_as_graph(textfile): parser = SpiceParser(source=textfile) circuit = parser.build_circuit() component_list = components(circuit) adj = {} for element in circuit.elements: element_id = component_list.index(element) if element_id not in adj: adj[element_id] = [] nodes = [pin.node for pin in element.pins] node_ids = [component_list.index(node) for node in nodes] adj[element_id].extend(node_ids) for node_id in node_ids: if node_id not in adj: adj[node_id] = [] adj[node_id].append(element_id) adj = nx.adjacency_matrix(nx.from_dict_of_lists(adj)).toarray() return component_list, adj
super().__init__() self.R('load', 'output', 'x', 10 @ u_Ω) #################################################################################################### #!# We read the generated netlist. kicad_netlist_path = os.path.join(os.path.realpath(os.path.dirname(__file__)), 'kicad-pyspice-example', 'kicad-pyspice-example.cir') parser = SpiceParser(path=kicad_netlist_path) #!# We build the circuit and translate the ground (5 to 0). circuit = parser.build_circuit(ground=5) #!# We include the operational amplifier module. circuit.include(spice_library['LMV981']) #!# We define the subcircuits. for subcircuit in (PowerIn(), Opamp(), JackIn(), JackOut()): circuit.subcircuit(subcircuit) # print(str(circuit)) #!# We perform a transient simulation. simulator = circuit.simulator(temperature=25, nominal_temperature=25) analysis = simulator.transient(step_time=100 @ u_us, end_time=3 @ u_ms) figure = plt.figure(1, (20, 10))
def __init__(self): super().__init__() self.R('load', 'output', 'x', 10) #################################################################################################### #!# We read the generated netlist. kicad_netlist_path = os.path.join(os.path.realpath(os.path.dirname(__file__)), 'kicad-pyspice-example', 'kicad-pyspice-example.cir') parser = SpiceParser(path=kicad_netlist_path) #!# We build the circuit and translate the ground (5 to 0). circuit = parser.build_circuit(ground=5) #!# We include the operational amplifier module. circuit.include(spice_library['LMV981']) #!# We define the subcircuits. for subcircuit in (PowerIn(), Opamp(), JackIn(), JackOut()): circuit.subcircuit(subcircuit) # print(str(circuit)) #!# We perform a transient simulation. simulator = circuit.simulator(temperature=25, nominal_temperature=25) analysis = simulator.transient(step_time=milli(.1), end_time=milli(3)) figure = plt.figure(1, (20, 10))
# #.lib CMOS_035_Spice_Model.lib tt # #.end # """ source = """ .title Test V1 vp GND dc 1.65 ac 0.5 M7 Vout /6 VDD VDD p_33 l=0.9u w=25.9u M6 Vout /3 GND GND n_33 l=1.4u w=92.04u M2 /3 vp /1 VDD p_33 l=0.9u w=51.78u M1 /2 vn /1 VDD p_33 l=0.9u w=51.78u M4 /3 /2 GND GND n_33 l=1.4u w=46.02u M3 /2 /2 GND GND n_33 l=1.4u w=46.02u M5 /1 /6 VDD VDD p_33 l=0.9u w=12.95u V0 VDD GND 3.3 M8 /6 /6 VDD VDD p_33 l=0.9u w=1.3u I1 /6 GND 10u .lib CMOS_035_Spice_Model.lib tt """.strip() parser = SpiceParser(source=source) circuit = parser.build_circuit() source2 = str(circuit) for line1, line2 in zip(source.splitlines(), source2.splitlines()): print('-' * 100) print(line1 + '|') print(line2 + '|') assert (line1 == line2)
#################################################################################################### circuit = Circuit('STM AN1476: Low-Cost Power Supply For Home Appliances') circuit.include(spice_library['1N4148']) # 1N5919B: 5.6 V, 3.0 W Zener Diode Voltage Regulator circuit.include(spice_library['d1n5919brl']) ac_line = circuit.AcLine('input', 'out', 'in', rms_voltage=230, frequency=50) circuit.R('load', 'out', circuit.gnd, kilo(1)) circuit.C('load', 'out', circuit.gnd, micro(220)) circuit.X('D1', '1N4148', circuit.gnd, 1) circuit.D(1, circuit.gnd, 1, model='DIODE1', off=True) circuit.X('Dz1', 'd1n5919brl', 1, 'out') circuit.C('ac', 1, 2, nano(470)) circuit.R('ac', 2, 'in', 470) # Fixme: , m=1, temperature='{25}' source = str(circuit) print(source) #################################################################################################### parser = SpiceParser(source=source) bootstrap_circuit = parser.build_circuit() bootstrap_source = str(bootstrap_circuit) print(bootstrap_source) assert(source == bootstrap_source)
# #.lib CMOS_035_Spice_Model.lib tt # #.end # """ source = """ .title Test V1 vp GND dc 1.65 ac 0.5 M7 Vout /6 VDD VDD p_33 l=0.9u w=25.9u M6 Vout /3 GND GND n_33 l=1.4u w=92.04u M2 /3 vp /1 VDD p_33 l=0.9u w=51.78u M1 /2 vn /1 VDD p_33 l=0.9u w=51.78u M4 /3 /2 GND GND n_33 l=1.4u w=46.02u M3 /2 /2 GND GND n_33 l=1.4u w=46.02u M5 /1 /6 VDD VDD p_33 l=0.9u w=12.95u V0 VDD GND 3.3 M8 /6 /6 VDD VDD p_33 l=0.9u w=1.3u I1 /6 GND 10u .lib CMOS_035_Spice_Model.lib tt """.strip() parser = SpiceParser(source=source) circuit = parser.build_circuit() source2 = str(circuit) for line1, line2 in zip(source.splitlines(), source2.splitlines()): print('-'*100) print(line1 + '|') print(line2 + '|') assert(line1 == line2)
# 1N5919B: 5.6 V, 3.0 W Zener Diode Voltage Regulator circuit.include(spice_library['d1n5919brl']) ac_line = circuit.AcLine('input', 'out', 'in', rms_voltage=230, frequency=50) circuit.R('load', 'out', circuit.gnd, kilo(1)) circuit.C('load', 'out', circuit.gnd, micro(220)) circuit.X('D1', '1N4148', circuit.gnd, 1) circuit.D(1, circuit.gnd, 1, model='DIODE1', off=True) circuit.X('Dz1', 'd1n5919brl', 1, 'out') circuit.C('ac', 1, 2, nano(470)) circuit.R('ac', 2, 'in', 470, m=1, temperature='{25}') source = str(circuit) print(source) #################################################################################################### parser = SpiceParser(source=source) bootstrap_circuit = parser.build_circuit() bootstrap_source = str(bootstrap_circuit) print(bootstrap_source) assert (source == bootstrap_source) #################################################################################################### # # End # ####################################################################################################