def setup(cls): bdc1 = core.ComponentInstance(dev.ebeam_bdc_te1550, [0, 1, 2, 3]) term1 = core.ComponentInstance(dev.ebeam_terminator_te1550, [2]) y1 = core.ComponentInstance(dev.ebeam_y_1550, [4, 0, 1]) gc1 = core.ComponentInstance(dev.ebeam_gc_te1550, [3, -2]) wg1 = core.ComponentInstance(dev.ebeam_wg_integral_1550, [4, -1], extras={'length': 40e-6}) cls.components = [bdc1, term1, y1, gc1, wg1] cls.nl = core.Netlist(components=cls.components)
def test_parsing_listoflists(self): bdc1 = core.ComponentInstance(dev.ebeam_bdc_te1550) term1 = core.ComponentInstance(dev.ebeam_terminator_te1550) y1 = core.ComponentInstance(dev.ebeam_y_1550) gc1 = core.ComponentInstance(dev.ebeam_gc_te1550) c1 = [bdc1, bdc1, bdc1, bdc1] p1 = [0, 1, 2, 3] c2 = [y1, y1, term1, gc1] p2 = [0, 1, 0, 0] data = zip(c1, p1, c2, p2) nl = core.Netlist() nl.load(data, formatter='ll')
def test_Simulation_MatchPorts(self): bdc1 = core.ComponentInstance(dev.ebeam_bdc_te1550, [0, 1, 2, 3]) term1 = core.ComponentInstance(dev.ebeam_terminator_te1550, [2]) y1 = core.ComponentInstance(dev.ebeam_y_1550, [-1, 0, 1]) gc1 = core.ComponentInstance(dev.ebeam_gc_te1550, [3, -2]) components = [bdc1, term1, y1, gc1] nl = core.Netlist(components=components) c1, n1, c2, n2 = sim.match_ports(3, nl.components) assert c1 == 0 assert n1 == 3 assert c2 == 3 assert n2 == 0
def test_netlist_InstancesFromComponentModels(self): @register_component_model class RingResonator(core.ComponentModel): ports = 4 s_parameters = ([1500, 1550, 1600], [0,0,0]) cachable = True nl = core.Netlist() c1 = core.ComponentInstance(RingResonator, [0,1,2,3], {'lay_x':3.1, 'lay_y':4}) c2 = core.ComponentInstance(RingResonator, [4,1,2,5]) nl.add_component(c1) nl.add_component(c2) assert len(nl.components) == 2 deregister_component_model('RingResonator')
def test_mzi(self): y1 = core.ComponentInstance(dev.ebeam_y_1550) y2 = core.ComponentInstance(dev.ebeam_y_1550) wg1 = core.ComponentInstance(dev.ebeam_wg_integral_1550, extras={'length':50e-6}) wg2 = core.ComponentInstance(dev.ebeam_wg_integral_1550, extras={'length':150e-6}) c1 = [y1, y1, y2, y2] p1 = [1, 2, 2, 1] c2 = [wg1, wg2, wg1, wg2] p2 = [0, 0, 1, 1] con = zip(c1, p1, c2, p2) nl = core.Netlist() nl.load(con, formatter='ll') simu = sim.Simulation(nl) freq = simu.freq_array zero2zero = abs(simu.s_parameters()[:, 0, 0])**2 zero2one = abs(simu.s_parameters()[:, 0, 1])**2 one2zero = abs(simu.s_parameters()[:, 1, 0])**2 one2one = abs(simu.s_parameters()[:, 1, 1])**2 # np.savez('test_simphony_test_mzi', freq=freq, zero2zero=zero2zero, zero2one=zero2one, one2zero=one2zero, one2one=one2one) expected = np.load(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'benchmarks', 'test_simphony_test_mzi.npz')) assert np.all(freq == expected['freq']) assert np.all(zero2zero == expected['zero2zero']) assert np.all(zero2one == expected['zero2one']) assert np.all(one2zero == expected['one2zero']) assert np.all(one2one == expected['one2one']) # import matplotlib.pyplot as plt # plt.subplot(221) # plt.plot(freq, zero2zero) # plt.subplot(222) # plt.plot(freq, zero2one) # plt.subplot(223) # plt.plot(freq, one2zero) # plt.subplot(224) # plt.plot(freq, one2one) # plt.suptitle("MZI") # plt.show()
def spice_netlist_export(self) -> (str, str, core.Netlist): """ This function gathers information from the current top cell in Klayout into a netlist for a photonic circuit. This netlist is used in simulations. Code for this function is taken and adapted from a function in 'SiEPIC-Tools/klayout_dot_config/python/SiEPIC/extend.py' which does the same thing, but to create a netlist for Lumerical INTERCONNECT. This function has parts of that one removed since they are not needed for this toolbox. """ import SiEPIC from SiEPIC import _globals from time import strftime from SiEPIC.utils import eng_str from SiEPIC.utils import get_technology TECHNOLOGY = get_technology() if not TECHNOLOGY['technology_name']: v = pya.MessageBox.warning( "Errors", "SiEPIC-Tools requires a technology to be chosen. \n\nThe active technology is displayed on the bottom-left of the KLayout window, next to the T. \n\nChange the technology using KLayout File | Layout Properties, then choose Technology and find the correct one (e.g., EBeam, GSiP).", pya.MessageBox.Ok) return 'x', 'x', 0, [0] # get the netlist from the entire layout nets, components = self.identify_nets() if not components: v = pya.MessageBox.warning("Errors", "No components found.", pya.MessageBox.Ok) return 'no', 'components', 0, ['found'] text_subckt = '* Spice output from KLayout SiEPIC-Tools v%s, %s.\n\n' % ( SiEPIC.__version__, strftime("%Y-%m-%d %H:%M:%S")) circuit_name = self.name.replace('.', '') # remove "." if '_' in circuit_name[0]: circuit_name = ''.join(circuit_name.split('_', 1)) # remove leading _ ioports = -1 for c in components: # optical nets: must be ordered electrical, optical IO, then optical nets_str = '' for p in c.pins: if p.type == _globals.PIN_TYPES.ELECTRICAL: nets_str += " " + c.component + '_' + str( c.idx) + '_' + p.pin_name for p in c.pins: if p.type == _globals.PIN_TYPES.OPTICALIO: nets_str += " N$" + str(ioports) ioports -= 1 #pinIOtype = any([p for p in c.pins if p.type == _globals.PIN_TYPES.OPTICALIO]) for p in c.pins: if p.type == _globals.PIN_TYPES.OPTICAL: if p.net.idx != None: nets_str += " N$" + str(p.net.idx) #if p.net.idx != None: # nets_str += " N$" + str(p.net.idx) else: nets_str += " N$" + str(ioports) ioports -= 1 # Check to see if this component is an Optical IO type. pinIOtype = any( [p for p in c.pins if p.type == _globals.PIN_TYPES.OPTICALIO]) component1 = c.component params1 = c.params text_subckt += ' %s %s %s ' % (component1.replace(' ', '_') + "_" + str(c.idx), nets_str, component1.replace(' ', '_')) x, y = c.Dcenter.x, c.Dcenter.y text_subckt += '%s lay_x=%s lay_y=%s\n' % \ (params1, eng_str(x * 1e-6), eng_str(y * 1e-6)) om = NetlistParser() om_components = om.parse_text(text_subckt) nl = core.Netlist() nl.components = om_components return text_subckt, "output", nl, om.external_list
'ng': 1.3 }) wg2 = core.ComponentInstance(dev.ebeam_wg_integral_1550, extras={ 'length': 150e-6, 'ne': 12.15, 'ng': -3.7 }) c1 = [y1, y1, y2, y2, bg_in, bg_out] p1 = [1, 2, 2, 1, 0, 0] c2 = [wg1, wg2, wg1, wg2, y1, y2] p2 = [0, 0, 1, 1, 0, 0] con = zip(c1, p1, c2, p2) nl = core.Netlist() nl.load(con, formatter='ll') simu = sim.Simulation(nl) freq = simu.freq_array zero2zero = np.log10(abs(simu.s_parameters()[:, 0, 0])**2) zero2one = np.log10(abs(simu.s_parameters()[:, 0, 1])**2) one2zero = abs(simu.s_parameters()[:, 1, 0])**2 one2one = abs(simu.s_parameters()[:, 1, 1])**2 # assert np.all(freq == expected['freq']) # assert np.all(zero2zero == expected['zero2zero']) # assert np.all(zero2one == expected['zero2one']) # assert np.all(one2zero == expected['one2zero']) # assert np.all(one2one == expected['one2one'])
def test_Netlist_unparameterized_initialization(self): self.nl = core.Netlist() for i in range(len(self.components)): self.nl.add_component(self.components[i]) assert len(self.nl.components) == len(self.components)
def test_Netlist_parameterized_initialization(self): self.nl = core.Netlist(components=self.components) assert self.nl.net_count == 4 assert len(self.nl.components) == len(self.components)
def test_4Port_Circuit(self): gc1 = core.ComponentInstance(dev.ebeam_gc_te1550) gc2 = core.ComponentInstance(dev.ebeam_gc_te1550) gc3 = core.ComponentInstance(dev.ebeam_gc_te1550) gc4 = core.ComponentInstance(dev.ebeam_gc_te1550) y1 = core.ComponentInstance(dev.ebeam_y_1550) y2 = core.ComponentInstance(dev.ebeam_y_1550) y3 = core.ComponentInstance(dev.ebeam_y_1550) bdc1 = core.ComponentInstance(dev.ebeam_bdc_te1550) bdc2 = core.ComponentInstance(dev.ebeam_bdc_te1550) term1 = core.ComponentInstance(dev.ebeam_terminator_te1550) wg1 = core.ComponentInstance(dev.ebeam_wg_integral_1550, extras={'length':165.51e-6}) wg2 = core.ComponentInstance(dev.ebeam_wg_integral_1550, extras={'length':247.73e-6}) wg3 = core.ComponentInstance(dev.ebeam_wg_integral_1550, extras={'length':642.91e-6}) wg4 = core.ComponentInstance(dev.ebeam_wg_integral_1550, extras={'length':391.06e-6}) wg5 = core.ComponentInstance(dev.ebeam_wg_integral_1550, extras={'length':10.45e-6}) wg6 = core.ComponentInstance(dev.ebeam_wg_integral_1550, extras={'length':10.45e-6}) wg7 = core.ComponentInstance(dev.ebeam_wg_integral_1550, extras={'length':10.45e-6}) wg8 = core.ComponentInstance(dev.ebeam_wg_integral_1550, extras={'length':10.45e-6}) wg9 = core.ComponentInstance(dev.ebeam_wg_integral_1550, extras={'length':162.29e-6}) wg10 = core.ComponentInstance(dev.ebeam_wg_integral_1550, extras={'length':205.47e-6}) connections = [] connections.append([gc1, 0, wg1, 1]) connections.append([gc3, 0, wg2, 1]) connections.append([bdc1, 3, wg1, 0]) connections.append([bdc1, 2, wg2, 0]) connections.append([gc2, 0, y1, 0]) connections.append([y1, 1, wg3, 0]) connections.append([y1, 2, wg4, 0]) connections.append([y2, 0, wg4, 1]) connections.append([y3, 0, wg3, 1]) connections.append([y2, 1, wg5, 1]) connections.append([bdc1, 0, wg5, 0]) connections.append([bdc1, 1, wg6, 1]) connections.append([y3, 2, wg6, 0]) connections.append([y2, 2, wg7, 0]) connections.append([y3, 1, wg8, 1]) connections.append([bdc2, 2, wg7, 1]) connections.append([bdc2, 3, wg8, 0]) connections.append([bdc2, 0, wg9, 0]) connections.append([term1, 0, wg9, 1]) connections.append([bdc2, 1, wg10, 0]) connections.append([gc4, 0, wg10, 1]) nl = core.Netlist() nl.load(connections, formatter='ll') simu = sim.Simulation(nl) freq = simu.freq_array two2zero = abs(simu.s_parameters()[:, 2, 0])**2 two2one = abs(simu.s_parameters()[:, 2, 1])**2 two2two = abs(simu.s_parameters()[:, 2, 2])**2 two2three = abs(simu.s_parameters()[:, 2, 3])**2 # np.savez('test_simphony_test_4Port_Circuit', freq=freq, two2zero=two2zero, two2one=two2one, two2two=two2two, two2three=two2three) expected = np.load(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'benchmarks', 'test_simphony_test_4Port_Circuit.npz')) assert np.all(freq == expected['freq']) assert np.all(two2zero == expected['two2zero']) assert np.all(two2one == expected['two2one']) assert np.all(two2two == expected['two2two']) assert np.all(two2three == expected['two2three'])