diff options
author | fossee | 2019-08-29 12:03:11 +0530 |
---|---|---|
committer | fossee | 2019-08-29 12:03:11 +0530 |
commit | fe3bd934634bb2dae1cadf35e7c6d59facbedf66 (patch) | |
tree | ab841ad9ca3d56f7eb85cb3650f6608b80656027 /src/kicadtoNgspice | |
parent | f7567ac99f21fb6c87d60f309f0aa71dee6ae975 (diff) | |
download | eSim-fe3bd934634bb2dae1cadf35e7c6d59facbedf66.tar.gz eSim-fe3bd934634bb2dae1cadf35e7c6d59facbedf66.tar.bz2 eSim-fe3bd934634bb2dae1cadf35e7c6d59facbedf66.zip |
adding files
Diffstat (limited to 'src/kicadtoNgspice')
20 files changed, 3122 insertions, 0 deletions
diff --git a/src/kicadtoNgspice/Analysis.py b/src/kicadtoNgspice/Analysis.py new file mode 100644 index 00000000..a573c540 --- /dev/null +++ b/src/kicadtoNgspice/Analysis.py @@ -0,0 +1,641 @@ + +from PyQt4 import QtGui +import TrackWidget +import os +from xml.etree import ElementTree as ET + +class Analysis(QtGui.QWidget): + """ + This class create Analysis Tab in KicadtoNgspice Window. + """ + def __init__(self,clarg1): + self.clarg1=clarg1 + QtGui.QWidget.__init__(self) + self.track_obj= TrackWidget.TrackWidget() + self.count =0 + self.parameter_cnt=0 + self.ac_entry_var={} + self.dc_entry_var={} + self.tran_entry_var={} + self.ac_parameter={} + self.dc_parameter={} + self.tran_parameter= {} + self.createAnalysisWidget() + + + + def createAnalysisWidget(self): + self.grid = QtGui.QGridLayout() + self.grid.addWidget(self.createCheckBox(),0,0) + self.grid.addWidget(self.createACgroup(),1,0) + self.grid.addWidget(self.createDCgroup(),2,0) + self.grid.addWidget(self.createTRANgroup(),3,0) + + try: + kicadFile = self.clarg1 + (projpath,filename)=os.path.split(kicadFile) + if os.path.isfile(os.path.join(projpath, 'analysis')): + print "Analysis file is present" + analysisfile = open(os.path.join(projpath,'analysis')) + content = analysisfile.readline() + print "Content of Analysis file :", content + contentlist= content.split() + if contentlist[0]== '.ac': + self.checkAC.setChecked(True) + self.acbox.setDisabled(False) + self.dcbox.setDisabled(True) + self.trbox.setDisabled(True) + self.track_obj.set_CheckBox["ITEMS"]="AC" + if contentlist[1]== 'lin': + self.Lin.setChecked(True) + self.track_obj.AC_type["ITEMS"]="lin" + elif contentlist[1]== 'dec': + self.Dec.setChecked(True) + self.track_obj.AC_type["ITEMS"]="dec" + elif contentlist[1]== 'oct': + self.Oct.setChecked(True) + self.track_obj.AC_type["ITEMS"]="oct" + + elif contentlist[0]== '.dc': + self.checkDC.setChecked(True) + self.dcbox.setDisabled(False) + self.acbox.setDisabled(True) + self.trbox.setDisabled(True) + self.track_obj.set_CheckBox["ITEMS"]="DC" + + elif contentlist[0]== '.tran': + self.checkTRAN.setChecked(True) + self.trbox.setDisabled(False) + self.acbox.setDisabled(True) + self.dcbox.setDisabled(True) + self.track_obj.set_CheckBox["ITEMS"]="TRAN" + + elif contentlist[0]== '.op': + self.checkDC.setChecked(True) + self.dcbox.setDisabled(False) + self.acbox.setDisabled(True) + self.trbox.setDisabled(True) + self.check.setChecked(True) + except: + self.checkTRAN.setChecked(True) + self.track_obj.set_CheckBox["ITEMS"]="TRAN" + + self.setLayout(self.grid) + self.show() + + def createCheckBox(self): + self.checkbox = QtGui.QGroupBox() + self.checkbox.setTitle("Select Analysis Type") + self.checkgrid = QtGui.QGridLayout() + + self.checkgroupbtn = QtGui.QButtonGroup() + self.checkAC = QtGui.QCheckBox("AC") + self.checkDC = QtGui.QCheckBox("DC") + self.checkTRAN = QtGui.QCheckBox("TRANSIENT") + self.checkgroupbtn.addButton(self.checkAC) + self.checkgroupbtn.addButton(self.checkDC) + self.checkgroupbtn.addButton(self.checkTRAN) + self.checkgroupbtn.setExclusive(True) + self.checkgroupbtn.buttonClicked.connect(self.enableBox) + + self.checkgrid.addWidget(self.checkAC,0,0) + self.checkgrid.addWidget(self.checkDC,0,1) + self.checkgrid.addWidget(self.checkTRAN,0,2) + self.checkbox.setLayout(self.checkgrid) + + return self.checkbox + + + def enableBox(self): + if self.checkAC.isChecked(): + self.acbox.setDisabled(False) + self.dcbox.setDisabled(True) + self.trbox.setDisabled(True) + self.track_obj.set_CheckBox["ITEMS"]="AC" + + elif self.checkDC.isChecked(): + self.dcbox.setDisabled(False) + self.acbox.setDisabled(True) + self.trbox.setDisabled(True) + self.track_obj.set_CheckBox["ITEMS"]="DC" + + elif self.checkTRAN.isChecked(): + self.trbox.setDisabled(False) + self.acbox.setDisabled(True) + self.dcbox.setDisabled(True) + self.track_obj.set_CheckBox["ITEMS"]="TRAN" + + def createACgroup(self): + kicadFile = self.clarg1 + (projpath,filename)=os.path.split(kicadFile) + project_name=os.path.basename(projpath) + check=1 + try: + f=open(os.path.join(projpath,project_name+"_Previous_Values.xml"),'r') + tree=ET.parse(f) + parent_root=tree.getroot() + for child in parent_root: + if child.tag=="analysis": + root=child + except: + check=0 + print "AC Previous Values XML is Empty" + + self.acbox = QtGui.QGroupBox() + self.acbox.setTitle("AC Analysis") + self.acbox.setDisabled(True) + self.acgrid = QtGui.QGridLayout() + self.radiobuttongroup= QtGui.QButtonGroup() + self.Lin = QtGui.QRadioButton("Lin") + self.Dec = QtGui.QRadioButton("Dec") + self.Oct = QtGui.QRadioButton("Oct") + self.radiobuttongroup.addButton(self.Lin) + self.radiobuttongroup.addButton(self.Dec) + self.radiobuttongroup.addButton(self.Oct) + self.radiobuttongroup.setExclusive(True) + self.Lin.setChecked(True) + self.track_obj.AC_type["ITEMS"]="lin" + self.radiobuttongroup.buttonClicked.connect(self.set_ac_type) + self.acgrid.addWidget(self.Lin,1,1) + self.acgrid.addWidget(self.Dec,1,2) + self.acgrid.addWidget(self.Oct,1,3) + self.acbox.setLayout(self.acgrid) + + self.scale = QtGui.QLabel("Scale") + self.start_fre_lable = QtGui.QLabel("Start Frequency") + self.stop_fre_lable = QtGui.QLabel("Stop Frequency") + self.no_of_points = QtGui.QLabel("No.of Points") + self.acgrid.addWidget(self.scale,1,0) + self.acgrid.addWidget(self.start_fre_lable,2,0) + self.acgrid.addWidget(self.stop_fre_lable,3,0) + self.acgrid.addWidget(self.no_of_points,4,0) + + self.count=0 + self.ac_entry_var[self.count] = QtGui.QLineEdit()#start + self.acgrid.addWidget(self.ac_entry_var[self.count],2,1) + self.ac_entry_var[self.count].setMaximumWidth(150) + self.count= self.count+1 + self.ac_entry_var[self.count] = QtGui.QLineEdit()#stop + self.acgrid.addWidget(self.ac_entry_var[self.count],3,1) + self.ac_entry_var[self.count].setMaximumWidth(150) + self.count= self.count+1 + self.ac_entry_var[self.count] = QtGui.QLineEdit()#no of pts + self.acgrid.addWidget(self.ac_entry_var[self.count],4,1) + self.ac_entry_var[self.count].setMaximumWidth(150) + + self.parameter_cnt=0 + self.start_fre_combo = QtGui.QComboBox() + self.start_fre_combo.addItem("Hz",) + self.start_fre_combo.addItem("KHz") + self.start_fre_combo.addItem("Meg") + self.start_fre_combo.addItem("GHz") + self.start_fre_combo.addItem("THz") + self.start_fre_combo.setMaximumWidth(150) + self.acgrid.addWidget(self.start_fre_combo,2,2) + self.ac_parameter[0]= "Hz" + try: + self.ac_parameter[self.parameter_cnt]= str(root[0][6].text) + except: + self.ac_parameter[self.parameter_cnt]= "Hz" + self.start_fre_combo.activated[str].connect(self.start_combovalue) + + self.parameter_cnt=self.parameter_cnt + 1 + self.stop_fre_combo = QtGui.QComboBox() + self.stop_fre_combo.addItem("Hz") + self.stop_fre_combo.addItem("KHz") + self.stop_fre_combo.addItem("Meg") + self.stop_fre_combo.addItem("GHz") + self.stop_fre_combo.addItem("THz") + self.stop_fre_combo.setMaximumWidth(150) + self.acgrid.addWidget(self.stop_fre_combo,3,2) + self.ac_parameter[1]= "Hz" + try: + self.ac_parameter[self.parameter_cnt]= str(root[0][7].text) + except: + self.ac_parameter[self.parameter_cnt]= "Hz" + self.stop_fre_combo.activated[str].connect(self.stop_combovalue) + + + self.track_obj.AC_entry_var["ITEMS"]=self.ac_entry_var + self.track_obj.AC_Parameter["ITEMS"]=self.ac_parameter + + #CSS + self.acbox.setStyleSheet(" \ + QGroupBox { border: 1px solid gray; border-radius: 9px; margin-top: 0.5em; } \ + QGroupBox::title { subcontrol-origin: margin; left: 10px; padding: 0 3px 0 3px; } \ + ") + if check: + try: + if root[0][0].text=="true": + self.Lin.setChecked(True) + self.Dec.setChecked(False) + self.Oct.setChecked(False) + elif root[0][1].text=="true": + self.Lin.setChecked(False) + self.Dec.setChecked(True) + self.Oct.setChecked(False) + elif root[0][2].text=="true": + self.Lin.setChecked(False) + self.Dec.setChecked(False) + self.Oct.setChecked(True) + else: + pass + self.ac_entry_var[0].setText(root[0][3].text) + self.ac_entry_var[1].setText(root[0][4].text) + self.ac_entry_var[2].setText(root[0][5].text) + index=self.start_fre_combo.findText(root[0][6].text) + self.start_fre_combo.setCurrentIndex(index) + index=self.stop_fre_combo.findText(root[0][7].text) + self.stop_fre_combo.setCurrentIndex(index) + except: + print "AC Analysis XML Parse Error" + + return self.acbox + + def start_combovalue(self, text): + self.ac_parameter[0]= str(text) + + def stop_combovalue(self, text): + self.ac_parameter[1]= str(text) + + def set_ac_type(self): + self.parameter_cnt=0 + if self.Lin.isChecked(): + self.track_obj.AC_type["ITEMS"]="lin" + elif self.Dec.isChecked(): + self.track_obj.AC_type["ITEMS"]= "dec" + elif self.Oct.isChecked(): + self.track_obj.AC_type["ITEMS"]="oct" + else: + pass + + def createDCgroup(self): + kicadFile = self.clarg1 + (projpath,filename)=os.path.split(kicadFile) + project_name=os.path.basename(projpath) + check=1 + try: + f=open(os.path.join(projpath,project_name+"_Previous_Values.xml"),'r') + tree=ET.parse(f) + parent_root=tree.getroot() + for child in parent_root: + if child.tag=="analysis": + root=child + except: + check=0 + print "DC Previous Values XML is empty" + + self.dcbox = QtGui.QGroupBox() + self.dcbox.setTitle("DC Analysis") + self.dcbox.setDisabled(True) + self.dcgrid = QtGui.QGridLayout() + self.dcbox.setLayout(self.dcgrid) + + self.source_name= QtGui.QLabel('Enter Source 1',self) + self.source_name.setMaximumWidth(150) + self.start= QtGui.QLabel('Start', self) + self.start.setMaximumWidth(150) + self.increment=QtGui.QLabel('Increment',self) + self.increment.setMaximumWidth(150) + self.stop=QtGui.QLabel('Stop',self) + self.stop.setMaximumWidth(150) + + self.source_name2= QtGui.QLabel('Enter Source 2',self) + self.source_name2.setMaximumWidth(150) + self.start2= QtGui.QLabel('Start', self) + self.start2.setMaximumWidth(150) + self.increment2=QtGui.QLabel('Increment',self) + self.increment2.setMaximumWidth(150) + self.stop2=QtGui.QLabel('Stop',self) + self.stop2.setMaximumWidth(150) + + self.dcgrid.addWidget(self.source_name,1,0) + self.dcgrid.addWidget(self.start,2,0) + self.dcgrid.addWidget(self.increment,3,0) + self.dcgrid.addWidget(self.stop,4,0) + + self.dcgrid.addWidget(self.source_name2,5,0) + self.dcgrid.addWidget(self.start2,6,0) + self.dcgrid.addWidget(self.increment2,7,0) + self.dcgrid.addWidget(self.stop2,8,0) + + self.count=0 + self.dc_entry_var[self.count] = QtGui.QLineEdit()#source + self.dcgrid.addWidget(self.dc_entry_var[self.count],1,1) + self.dc_entry_var[self.count].setMaximumWidth(150) + self.count= self.count+1 + self.dc_entry_var[self.count] = QtGui.QLineEdit()#start + self.dcgrid.addWidget(self.dc_entry_var[self.count],2,1) + self.dc_entry_var[self.count].setMaximumWidth(150) + self.count= self.count+1 + self.dc_entry_var[self.count] = QtGui.QLineEdit()#increment + self.dcgrid.addWidget(self.dc_entry_var[self.count],3,1) + self.dc_entry_var[self.count].setMaximumWidth(150) + self.count= self.count+1 + self.dc_entry_var[self.count] = QtGui.QLineEdit()#stop + self.dcgrid.addWidget(self.dc_entry_var[self.count],4,1) + self.dc_entry_var[self.count].setMaximumWidth(150) + self.count=self.count+1 + + self.dc_entry_var[self.count] = QtGui.QLineEdit()#source + self.dcgrid.addWidget(self.dc_entry_var[self.count],5,1) + self.dc_entry_var[self.count].setMaximumWidth(150) + self.count= self.count+1 + self.dc_entry_var[self.count] = QtGui.QLineEdit()#start + self.dcgrid.addWidget(self.dc_entry_var[self.count],6,1) + self.dc_entry_var[self.count].setMaximumWidth(150) + self.count= self.count+1 + self.dc_entry_var[self.count] = QtGui.QLineEdit()#increment + self.dcgrid.addWidget(self.dc_entry_var[self.count],7,1) + self.dc_entry_var[self.count].setMaximumWidth(150) + self.count= self.count+1 + self.dc_entry_var[self.count] = QtGui.QLineEdit()#stop + self.dcgrid.addWidget(self.dc_entry_var[self.count],8,1) + self.dc_entry_var[self.count].setMaximumWidth(150) + + self.parameter_cnt=0 + self.start_combo=QtGui.QComboBox(self) + self.start_combo.setMaximumWidth(150) + self.start_combo.addItem('Volts or Amperes') + self.start_combo.addItem('mV or mA') + self.start_combo.addItem('uV or uA') + self.start_combo.addItem("nV or nA") + self.start_combo.addItem("pV or pA") + self.dcgrid.addWidget(self.start_combo,2,2) + try: + self.dc_parameter[self.parameter_cnt]= str(root[1][5].text) + except: + self.dc_parameter[self.parameter_cnt]= "Volts or Amperes" + self.start_combo.activated[str].connect(self.start_changecombo) + self.parameter_cnt= self.parameter_cnt+1 + + self.increment_combo=QtGui.QComboBox(self) + self.increment_combo.setMaximumWidth(150) + self.increment_combo.addItem("Volts or Amperes") + self.increment_combo.addItem("mV or mA") + self.increment_combo.addItem("uV or uA") + self.increment_combo.addItem("nV or nA") + self.increment_combo.addItem("pV or pA") + self.dcgrid.addWidget(self.increment_combo,3,2) + try: + self.dc_parameter[self.parameter_cnt]= str(root[1][6].text) + except: + self.dc_parameter[self.parameter_cnt]= "Volts or Amperes" + self.increment_combo.activated[str].connect(self.increment_changecombo) + self.parameter_cnt= self.parameter_cnt+1 + + self.stop_combo=QtGui.QComboBox(self) + self.stop_combo.setMaximumWidth(150) + self.stop_combo.addItem("Volts or Amperes") + self.stop_combo.addItem("mV or mA") + self.stop_combo.addItem("uV or uA") + self.stop_combo.addItem("nV or nA") + self.stop_combo.addItem("pV or pA") + self.dcgrid.addWidget(self.stop_combo,4,2) + try: + self.dc_parameter[self.parameter_cnt]= str(root[1][7].text) + except: + self.dc_parameter[self.parameter_cnt]= "Volts or Amperes" + self.stop_combo.activated[str].connect(self.stop_changecombo) + self.parameter_cnt= self.parameter_cnt+1 + + self.start_combo2=QtGui.QComboBox(self) + self.start_combo2.setMaximumWidth(150) + self.start_combo2.addItem('Volts or Amperes') + self.start_combo2.addItem('mV or mA') + self.start_combo2.addItem('uV or uA') + self.start_combo2.addItem("nV or nA") + self.start_combo2.addItem("pV or pA") + self.dcgrid.addWidget(self.start_combo2,6,2) + try: + self.dc_parameter[self.parameter_cnt]= str(root[1][12].text) + except: + self.dc_parameter[self.parameter_cnt]= "Volts or Amperes" + self.start_combo2.activated[str].connect(self.start_changecombo2) + self.parameter_cnt= self.parameter_cnt+1 + + self.increment_combo2=QtGui.QComboBox(self) + self.increment_combo2.setMaximumWidth(150) + self.increment_combo2.addItem("Volts or Amperes") + self.increment_combo2.addItem("mV or mA") + self.increment_combo2.addItem("uV or uA") + self.increment_combo2.addItem("nV or nA") + self.increment_combo2.addItem("pV or pA") + self.dcgrid.addWidget(self.increment_combo2,7,2) + try: + self.dc_parameter[self.parameter_cnt]= str(root[1][13].text) + except: + self.dc_parameter[self.parameter_cnt]= "Volts or Amperes" + self.increment_combo2.activated[str].connect(self.increment_changecombo2) + self.parameter_cnt= self.parameter_cnt+1 + + self.stop_combo2=QtGui.QComboBox(self) + self.stop_combo2.setMaximumWidth(150) + self.stop_combo2.addItem("Volts or Amperes") + self.stop_combo2.addItem("mV or mA") + self.stop_combo2.addItem("uV or uA") + self.stop_combo2.addItem("nV or nA") + self.stop_combo2.addItem("pV or pA") + self.dcgrid.addWidget(self.stop_combo2,8,2) + try: + self.dc_parameter[self.parameter_cnt]= str(root[1][14].text) + + except: + self.dc_parameter[self.parameter_cnt]= "Volts or Amperes" + self.stop_combo2.activated[str].connect(self.stop_changecombo2) + self.parameter_cnt= self.parameter_cnt+1 + + self.check=QtGui.QCheckBox('Operating Point Analysis',self) + try: + self.track_obj.op_check.append(str(root[1][4].text())) + except: + self.track_obj.op_check.append(0) + #QtCore.QObject.connect(check,SIGNAL("stateChanged()"),check,SLOT("checkedSlot")) + self.check.stateChanged.connect(self.setflag) + #self.flagcheck = 1 + #self.flagcheck= 2 + self.dcgrid.addWidget(self.check,9,1,9,2) + self.track_obj.DC_entry_var["ITEMS"]=self.dc_entry_var + self.track_obj.DC_Parameter["ITEMS"]=self.dc_parameter + + #CSS + self.dcbox.setStyleSheet(" \ + QGroupBox { border: 1px solid gray; border-radius: 9px; margin-top: 0.5em; } \ + QGroupBox::title { subcontrol-origin: margin; left: 10px; padding: 0 3px 0 3px; } \ + ") + if check: + try: + self.dc_entry_var[0].setText(root[1][0].text) + self.dc_entry_var[1].setText(root[1][1].text) + self.dc_entry_var[2].setText(root[1][2].text) + self.dc_entry_var[3].setText(root[1][3].text) + index=self.start_combo.findText(root[1][5].text) + self.start_combo.setCurrentIndex(index) + index=self.increment_combo.findText(root[1][6].text) + self.increment_combo.setCurrentIndex(index) + index=self.stop_combo.findText(root[1][7].text) + self.stop_combo.setCurrentIndex(index) + self.dc_entry_var[4].setText(root[1][8].text) + self.dc_entry_var[5].setText(root[1][9].text) + self.dc_entry_var[6].setText(root[1][10].text) + self.dc_entry_var[7].setText(root[1][11].text) + index=self.start_combo2.findText(root[1][12].text) + self.start_combo2.setCurrentIndex(index) + index=self.increment_combo2.findText(root[1][13].text) + self.increment_combo2.setCurrentIndex(index) + index=self.stop_combo2.findText(root[1][14].text) + self.stop_combo2.setCurrentIndex(index) + + if root[1][4].text== 1: + self.check.setChecked(True) + else: + self.check.setChecked(False) + except: + print "DC Analysis XML Parse Error" + + return self.dcbox + + def start_changecombo(self,text): + self.dc_parameter[0]=str(text) + + def increment_changecombo(self,text): + self.dc_parameter[1]=str(text) + + def stop_changecombo(self,text): + self.dc_parameter[2]=str(text) + + def start_changecombo2(self,text): + self.dc_parameter[3]=str(text) + + def increment_changecombo2(self,text): + self.dc_parameter[4]=str(text) + + def stop_changecombo2(self,text): + self.dc_parameter[5]=str(text) + + def setflag(self): + if self.check.isChecked(): + self.track_obj.op_check.append(1) + else: + self.track_obj.op_check.append(0) + + def createTRANgroup(self): + kicadFile = self.clarg1 + (projpath,filename)=os.path.split(kicadFile) + project_name=os.path.basename(projpath) + check=1 + try: + f=open(os.path.join(projpath,project_name+"_Previous_Values.xml"),'r') + tree=ET.parse(f) + parent_root=tree.getroot() + for child in parent_root: + if child.tag=="analysis": + root=child + except: + check=0 + print "Transient Previous Values XML is Empty" + + self.trbox = QtGui.QGroupBox() + self.trbox.setTitle("Transient Analysis") + #self.trbox.setDisabled(True) + self.trgrid = QtGui.QGridLayout() + self.trbox.setLayout(self.trgrid) + + self.start = QtGui.QLabel("Start Time") + self.step = QtGui.QLabel("Step Time") + self.stop = QtGui.QLabel("Stop Time") + self.trgrid.addWidget(self.start,1,0) + self.trgrid.addWidget(self.step,2,0) + self.trgrid.addWidget(self.stop,3,0) + self.count=0 + + self.tran_entry_var[self.count] = QtGui.QLineEdit() + self.trgrid.addWidget(self.tran_entry_var[self.count],1,1) + self.tran_entry_var[self.count].setMaximumWidth(150) + self.count= self.count+1 + self.tran_entry_var[self.count] = QtGui.QLineEdit() + self.trgrid.addWidget(self.tran_entry_var[self.count],2,1) + self.tran_entry_var[self.count].setMaximumWidth(150) + self.count= self.count+1 + self.tran_entry_var[self.count] = QtGui.QLineEdit() + self.trgrid.addWidget(self.tran_entry_var[self.count],3,1) + self.tran_entry_var[self.count].setMaximumWidth(150) + self.count= self.count+1 + + self.parameter_cnt=0 + self.start_combobox = QtGui.QComboBox() + self.start_combobox.addItem("Sec") + self.start_combobox.addItem("ms") + self.start_combobox.addItem("us") + self.start_combobox.addItem("ns") + self.start_combobox.addItem("ps") + self.trgrid.addWidget(self.start_combobox,1,3) + try: + self.tran_parameter[self.parameter_cnt]= str(root[2][3].text) + except: + self.tran_parameter[self.parameter_cnt]= "Sec" + self.start_combobox.activated[str].connect(self.start_combo_change) + self.parameter_cnt= self.parameter_cnt+1 + + self.step_combobox = QtGui.QComboBox() + self.step_combobox.addItem("Sec") + self.step_combobox.addItem("ms") + self.step_combobox.addItem("us") + self.step_combobox.addItem("ns") + self.step_combobox.addItem("ps") + self.trgrid.addWidget(self.step_combobox,2,3) + try: + self.tran_parameter[self.parameter_cnt]= str(root[2][4].text) + except: + self.tran_parameter[self.parameter_cnt]= "Sec" + self.step_combobox.activated[str].connect(self.step_combo_change) + self.parameter_cnt= self.parameter_cnt+1 + + self.stop_combobox = QtGui.QComboBox() + self.stop_combobox.addItem("Sec") + self.stop_combobox.addItem("ms") + self.stop_combobox.addItem("us") + self.stop_combobox.addItem("ns") + self.stop_combobox.addItem("ps") + self.trgrid.addWidget(self.stop_combobox,3,3) + try: + self.tran_parameter[self.parameter_cnt]= str(root[2][5].text) + except: + self.tran_parameter[self.parameter_cnt]= "Sec" + self.stop_combobox.activated[str].connect(self.stop_combo_change) + self.parameter_cnt= self.parameter_cnt+1 + + self.track_obj.TRAN_entry_var["ITEMS"]=self.tran_entry_var + self.track_obj.TRAN_Parameter["ITEMS"]=self.tran_parameter + + #CSS + self.trbox.setStyleSheet(" \ + QGroupBox { border: 1px solid gray; border-radius: 9px; margin-top: 0.5em; } \ + QGroupBox::title { subcontrol-origin: margin; left: 10px; padding: 0 3px 0 3px; } \ + ") + if check: + try: + self.tran_entry_var[0].setText(root[2][0].text) + self.tran_entry_var[1].setText(root[2][1].text) + self.tran_entry_var[2].setText(root[2][2].text) + index=self.start_combobox.findText(root[2][3].text) + self.start_combobox.setCurrentIndex(index) + index=self.step_combobox.findText(root[2][4].text) + self.step_combobox.setCurrentIndex(index) + + index=self.stop_combobox.findText(root[2][5].text) + self.stop_combobox.setCurrentIndex(index) + except: + print "Transient Analysis XML Parse Error" + + + return self.trbox + + def start_combo_change(self,text): + self.tran_parameter[0]=str(text) + + def step_combo_change(self,text): + self.tran_parameter[1]=str(text) + + def stop_combo_change(self,text): + self.tran_parameter[2]=str(text) diff --git a/src/kicadtoNgspice/Analysis.pyc b/src/kicadtoNgspice/Analysis.pyc Binary files differnew file mode 100644 index 00000000..20c0689e --- /dev/null +++ b/src/kicadtoNgspice/Analysis.pyc diff --git a/src/kicadtoNgspice/Convert.py b/src/kicadtoNgspice/Convert.py new file mode 100644 index 00000000..f02435d2 --- /dev/null +++ b/src/kicadtoNgspice/Convert.py @@ -0,0 +1,454 @@ +from PyQt4 import QtGui + +import os +import shutil +import TrackWidget +from xml.etree import ElementTree as ET + +class Convert: + """ + This class has all the necessary function required to convert kicad netlist to ngspice netlist. + """ + def __init__(self,sourcelisttrack,source_entry_var,schematicInfo,clarg1): + self.sourcelisttrack = sourcelisttrack + self.schematicInfo = schematicInfo + self.entry_var = source_entry_var + self.sourcelistvalue = [] + self.clarg1=clarg1 + + + def addSourceParameter(self): + """ + This function add the source details to schematicInfo + """ + + self.start = 0 + self.end = 0 + + for compline in self.sourcelisttrack: + self.index = compline[0] + self.addline = self.schematicInfo[self.index] + if compline[1] == 'sine': + try: + self.start = compline[2] + self.end = compline[3] + vo_val = str(self.entry_var[self.start].text()) if len(str(self.entry_var[self.start].text())) > 0 else '0' + va_val = str(self.entry_var[self.start+1].text()) if len(str(self.entry_var[self.start+1].text())) > 0 else '0' + freq_val = str(self.entry_var[self.start+2].text()) if len(str(self.entry_var[self.start+2].text())) > 0 else '0' + td_val = str(self.entry_var[self.start+3].text()) if len(str(self.entry_var[self.start+3].text())) > 0 else '0' + theta_val = str(self.entry_var[self.end].text()) if len(str(self.entry_var[self.end].text())) > 0 else '0' + self.addline = self.addline.partition('(')[0] + "("+vo_val+" "+va_val+" "+freq_val+" "+td_val+" "+theta_val+")" + self.sourcelistvalue.append([self.index,self.addline]) + except: + print "Caught an exception in sine voltage source ",self.addline + + elif compline[1] == 'pulse': + try: + self.start = compline[2] + self.end = compline[3] + v1_val = str(self.entry_var[self.start].text()) if len(str(self.entry_var[self.start].text())) > 0 else '0' + v2_val = str(self.entry_var[self.start+1].text()) if len(str(self.entry_var[self.start+1].text())) > 0 else '0' + td_val = str(self.entry_var[self.start+2].text()) if len(str(self.entry_var[self.start+2].text())) > 0 else '0' + tr_val = str(self.entry_var[self.start+3].text()) if len(str(self.entry_var[self.start+3].text())) > 0 else '0' + tf_val = str(self.entry_var[self.start+4].text()) if len(str(self.entry_var[self.start+4].text())) > 0 else '0' + pw_val = str(self.entry_var[self.start+5].text()) if len(str(self.entry_var[self.start+5].text())) > 0 else '0' + tp_val = str(self.entry_var[self.end].text()) if len(str(self.entry_var[self.end].text())) > 0 else '0' + + self.addline = self.addline.partition('(')[0] + "("+v1_val+" "+v2_val+" "+td_val+" "+tr_val+" "+tf_val+" "+pw_val+" "+tp_val+")" + self.sourcelistvalue.append([self.index,self.addline]) + except: + print "Caught an exception in pulse voltage source ",self.addline + + elif compline[1] == 'pwl': + try: + self.start = compline[2] + self.end = compline[3] + t_v_val = str(self.entry_var[self.start].text()) if len(str(self.entry_var[self.start].text())) > 0 else '0 0' + self.addline = self.addline.partition('(')[0] + "("+t_v_val+")" + self.sourcelistvalue.append([self.index,self.addline]) + except: + print "Caught an exception in pwl voltage source ",self.addline + + elif compline[1] == 'ac': + try: + self.start = compline[2] + self.end = compline[3] + va_val=str(self.entry_var[self.start].text()) if len(str(self.entry_var[self.start].text())) > 0 else '0' + ph_val=str(self.entry_var[self.start+1].text()) if len(str(self.entry_var[self.start+1].text())) > 0 else '0' + self.addline = ' '.join(self.addline.split()) + self.addline = self.addline.partition('ac')[0] +" "+'ac'+" "+ va_val+" "+ph_val + self.sourcelistvalue.append([self.index,self.addline]) + except: + print "Caught an exception in ac voltage source ",self.addline + + elif compline[1] == 'dc': + try: + self.start = compline[2] + self.end = compline[3] + v1_val = str(self.entry_var[self.start].text()) if len(str(self.entry_var[self.start].text())) > 0 else '0' + self.addline = ' '.join(self.addline.split()) + self.addline = self.addline.partition('dc')[0] + " " +'dc'+ " "+v1_val + self.sourcelistvalue.append([self.index,self.addline]) + except: + print "Caught an exception in dc voltage source",self.addline + + elif compline[1] == 'exp': + try: + self.start = compline[2] + self.end = compline[3] + v1_val = str(self.entry_var[self.start].text()) if len(str(self.entry_var[self.start].text())) > 0 else '0' + v2_val = str(self.entry_var[self.start+1].text()) if len(str(self.entry_var[self.start+1].text())) > 0 else '0' + td1_val = str(self.entry_var[self.start+2].text()) if len(str(self.entry_var[self.start+2].text())) > 0 else '0' + tau1_val = str(self.entry_var[self.start+3].text()) if len(str(self.entry_var[self.start+3].text())) > 0 else '0' + td2_val = str(self.entry_var[self.start+4].text()) if len(str(self.entry_var[self.start+4].text())) > 0 else '0' + tau2_val = str(self.entry_var[self.end].text()) if len(str(self.entry_var[self.end].text())) > 0 else '0' + + self.addline = self.addline.partition('(')[0] + "("+v1_val+" "+v2_val+" "+td1_val+" "+tau1_val+" "+td2_val+" "+tau2_val+")" + self.sourcelistvalue.append([self.index,self.addline]) + except: + print "Caught an exception in exp voltage source ",self.addline + + #Updating Schematic with source value + for item in self.sourcelistvalue: + del self.schematicInfo[item[0]] + self.schematicInfo.insert(item[0],item[1]) + + return self.schematicInfo + + + def analysisInsertor(self,ac_entry_var,dc_entry_var, tran_entry_var,set_checkbox,ac_parameter,dc_parameter,tran_parameter,ac_type,op_check): + """ + This function creates an analysis file in current project + """ + self.ac_entry_var = ac_entry_var + self.dc_entry_var = dc_entry_var + self.tran_entry_var = tran_entry_var + self.set_checkbox = set_checkbox + self.ac_parameter= ac_parameter + self.dc_parameter= dc_parameter + self.trans_parameter = tran_parameter + self.ac_type= ac_type + self.op_check = op_check + self.no=0 + + self.variable=self.set_checkbox + self.direct= self.clarg1 + (filepath, filemname)= os.path.split(self.direct) + self.Fileopen = os.path.join(filepath, "analysis") + self.writefile= open(self.Fileopen,"w") + if self.variable== 'AC': + self.no=0 + self.writefile.write(".ac"+' ' + self.ac_type + ' '+ str(self.defaultvalue(self.ac_entry_var[self.no+2].text()))+' ' + str(self.defaultvalue(self.ac_entry_var[self.no].text())) + self.ac_parameter[self.no]+ ' ' + str(self.defaultvalue(self.ac_entry_var[self.no+1].text())) + self.ac_parameter[self.no+1] ) + + elif self.variable=='DC': + if self.op_check[-1] == 1: + self.no=0 + self.writefile.write(".op") + elif self.op_check[-1] == 0: + self.no=0 + self.writefile.write(".dc" +' '+ str(self.dc_entry_var[self.no].text())+ ' '+ str(self.defaultvalue(self.dc_entry_var[self.no+1].text())) + self.converttosciform(self.dc_parameter[self.no]) + ' '+ str(self.defaultvalue(self.dc_entry_var[self.no+3].text()))+ self.converttosciform(self.dc_parameter[self.no+2]) + ' '+ str(self.defaultvalue(self.dc_entry_var[self.no+2].text())) + self.converttosciform(self.dc_parameter[self.no+1])) + + if self.dc_entry_var[self.no+4].text(): + self.writefile.write(' '+ str(self.defaultvalue(self.dc_entry_var[self.no+4].text()))+ ' '+ str(self.defaultvalue(self.dc_entry_var[self.no+5].text())) + self.converttosciform(self.dc_parameter[self.no+3])+ ' '+ str(self.defaultvalue(self.dc_entry_var[self.no+7].text()))+ self.converttosciform(self.dc_parameter[self.no+5])+ ' ' + str(self.defaultvalue(self.dc_entry_var[self.no+6].text()))+ self.converttosciform(self.dc_parameter[self.no+4])) + + elif self.variable == 'TRAN': + self.no= 0 + self.writefile.write(".tran" + ' '+ str(self.defaultvalue(self.tran_entry_var[self.no+1].text())) + self.converttosciform(self.trans_parameter[self.no+1]) + ' ' + str(self.defaultvalue(self.tran_entry_var[self.no+2].text())) + self.converttosciform(self.trans_parameter[self.no+2])+' '+ str(self.defaultvalue(self.tran_entry_var[self.no].text()))+ self.converttosciform(self.trans_parameter[self.no])) + + else: + pass + self.writefile.close() + + def converttosciform(self, string_obj): + """ + This function is used for scientific conversion. + """ + self.string_obj = string_obj + if self.string_obj[0] == 'm': + return "e-03" + elif self.string_obj[0] == 'u': + return "e-06" + elif self.string_obj[0] == 'n': + return "e-09" + elif self.string_obj[0] == 'p': + return "e-12" + else: + return "e-00" + + def defaultvalue(self, value): + """ + This function select default value as 0 if Analysis widget do not hold any value. + """ + self.value= value + if self.value == '': + return 0 + else: + return self.value + + + def addModelParameter(self,schematicInfo): + """ + This function add the Ngspice Model details to schematicInfo + """ + + #Create object of TrackWidget + self.obj_track = TrackWidget.TrackWidget() + + #List to store model line + addmodelLine = [] + modelParamValue = [] + + for line in self.obj_track.modelTrack: + #print "Model Track :",line + if line[2] == 'transfo': + try: + start=line[7] + end=line[8] + num_turns=str(self.obj_track.model_entry_var[start+1].text()) + + if num_turns=="": num_turns="310" + h_array= "H_array = [ " + b_array = "B_array = [ " + h1=str(self.obj_track.model_entry_var[start].text()) + b1=str(self.obj_track.model_entry_var[start+5].text()) + + if len(h1)!=0 and len(b1)!=0: + h_array=h_array+h1+" " + b_array=b_array+b1+" " + bh_array = h_array+" ] " + b_array+" ]" + else: + bh_array = "H_array = [-1000 -500 -375 -250 -188 -125 -63 0 63 125 188 250 375 500 1000] B_array = [-3.13e-3 -2.63e-3 -2.33e-3 -1.93e-3 -1.5e-3 -6.25e-4 -2.5e-4 0 2.5e-4 6.25e-4 1.5e-3 1.93e-3 2.33e-3 2.63e-3 3.13e-3]" + area=str(self.obj_track.model_entry_var[start+2].text()) + length=str(self.obj_track.model_entry_var[start+3].text()) + if area=="": area="1" + if length=="":length="0.01" + num_turns2=str(self.obj_track.model_entry_var[start+4].text()) + if num_turns2=="": num_turns2="620" + addmodelLine=".model "+line[3]+"_primary lcouple (num_turns= "+num_turns+")" + modelParamValue.append([line[0],addmodelLine,"*primary lcouple"]) + addmodelLine=".model "+line[3]+"_iron_core core ("+bh_array+" area = "+area+" length ="+length +")" + modelParamValue.append([line[0],addmodelLine,"*iron core"]) + addmodelLine=".model "+line[3]+"_secondary lcouple (num_turns ="+num_turns2+ ")" + modelParamValue.append([line[0],addmodelLine,"*secondary lcouple"]) + except Exception as e: + print "Caught an exception in transfo model ",line[1] + print "Exception Message : ",str(e) + + elif line[2] == 'ic': + try: + start=line[7] + end=line[8] + for key,value in line[9].iteritems(): + initVal = str(self.obj_track.model_entry_var[value].text()) + if initVal=="":initVal="0" + node = line[1].split()[1] #Extracting node from model line + addmodelLine = ".ic v("+node+")="+initVal + modelParamValue.append([line[0],addmodelLine,line[4]]) + except Exception as e: + print "Caught an exception in initial condition ",line[1] + print "Exception Message : ",str(e) + + + else: + try: + start = line[7] + end = line[8] + addmodelLine=".model "+ line[3]+" "+line[2]+"(" + for key,value in line[9].iteritems(): + #print "Tags: ",key + #print "Value: ",value + #Checking for default value and accordingly assign param and default. + if ':' in key: + key = key.split(':') + param = key[0] + default = key[1] + else: + param = key + default = 0 + #Cheking if value is iterable.its for vector + if hasattr(value, '__iter__'): + addmodelLine += param+"=[" + for lineVar in value: + if str(self.obj_track.model_entry_var[lineVar].text()) == "": + paramVal = default + else: + paramVal = str(self.obj_track.model_entry_var[lineVar].text()) + addmodelLine += paramVal+" " + addmodelLine += "] " + else: + if str(self.obj_track.model_entry_var[value].text()) == "": + paramVal = default + else: + paramVal = str(self.obj_track.model_entry_var[value].text()) + + addmodelLine += param+"="+paramVal+" " + + + addmodelLine += ") " + modelParamValue.append([line[0],addmodelLine,line[4]]) + except Exception as e: + print "Caught an exception in model ",line[1] + print "Exception Message : ",str(e) + + + #Adding it to schematic + for item in modelParamValue: + if ".ic" in item[1]: + schematicInfo.insert(0,item[1]) + schematicInfo.insert(0,item[2]) + else: + schematicInfo.append(item[2]) #Adding Comment + schematicInfo.append(item[1]) #Adding model line + + return schematicInfo + + def addDeviceLibrary(self,schematicInfo,kicadFile): + """ + This function add the library details to schematicInfo + """ + + (projpath,filename) = os.path.split(kicadFile) + + + deviceLibList = self.obj_track.deviceModelTrack + deviceLine = {} #Key:Index, Value:with its updated line in the form of list + includeLine = [] #All .include line list + + if not deviceLibList: + print "No Library Added in the schematic" + pass + else: + for eachline in schematicInfo: + words = eachline.split() + if words[0] in deviceLibList: + print "Found Library line" + index = schematicInfo.index(eachline) + completeLibPath = deviceLibList[words[0]] + (libpath,libname) = os.path.split(completeLibPath) + print "Library Path :",libpath + #Copying library from devicemodelLibrary to Project Path + #Special case for MOSFET + if eachline[0] == 'm': + #For mosfet library name come along with MOSFET dimension information + tempStr = libname.split(':') + libname = tempStr[0] + dimension = tempStr[1] + #Replace last word with library name + #words[-1] = libname.split('.')[0] + words[-1] = self.getRefrenceName(libname,libpath) + #Appending Dimension of MOSFET + words.append(dimension) + deviceLine[index] = words + includeLine.append(".include "+libname) + + #src = completeLibPath.split(':')[0] # <----- Not working in Windows + + (src_path,src_lib) = os.path.split(completeLibPath) + src_lib = src_lib.split(':')[0] + src = os.path.join(src_path,src_lib) + dst = projpath + shutil.copy2(src, dst) + else: + #Replace last word with library name + #words[-1] = libname.split('.')[0] + words[-1] = self.getRefrenceName(libname,libpath) + deviceLine[index] = words + includeLine.append(".include "+libname) + + src = completeLibPath + dst = projpath + shutil.copy2(src,dst) + + else: + pass + + + #Adding device line to schematicInfo + for index,value in deviceLine.iteritems(): + #Update the device line + strLine = " ".join(str(item) for item in value) + schematicInfo[index] = strLine + + #This has to be second i.e after deviceLine details + #Adding .include line to Schematic Info at the start of line + for item in list(set(includeLine)): + schematicInfo.insert(0,item) + + + return schematicInfo + + def addSubcircuit(self,schematicInfo,kicadFile): + """ + This function add the subcircuit to schematicInfo + """ + + (projpath,filename) = os.path.split(kicadFile) + + subList = self.obj_track.subcircuitTrack + subLine = {} #Key:Index, Value:with its updated line in the form of list + includeLine = [] #All .include line list + + if len(self.obj_track.subcircuitList) != len(self.obj_track.subcircuitTrack): + self.msg = QtGui.QErrorMessage() + self.msg.showMessage("Conversion failed. Please add all Subcircuits.") + self.msg.setWindowTitle("Error Message") + self.msg.show() + raise Exception('All subcircuit directories need to be specified.') + elif not subList: + print "No Subcircuit Added in the schematic" + pass + else: + for eachline in schematicInfo: + words = eachline.split() + if words[0] in subList: + print "Found Subcircuit line" + index = schematicInfo.index(eachline) + completeSubPath = subList[words[0]] + (subpath,subname) = os.path.split(completeSubPath) + print "Library Path :",subpath + #Copying library from devicemodelLibrary to Project Path + + #Replace last word with library name + words[-1] = subname.split('.')[0] + subLine[index] = words + includeLine.append(".include "+subname+".sub") + + src = completeSubPath + dst = projpath + print os.listdir(src) + for files in os.listdir(src): + if os.path.isfile(os.path.join(src,files)): + if files != "analysis": + shutil.copy2(os.path.join(src,files),dst) + else: + pass + + + #Adding subcircuit line to schematicInfo + for index,value in subLine.iteritems(): + #Update the subcircuit line + strLine = " ".join(str(item) for item in value) + schematicInfo[index] = strLine + + #This has to be second i.e after subcircuitLine details + #Adding .include line to Schematic Info at the start of line + for item in list(set(includeLine)): + schematicInfo.insert(0,item) + + return schematicInfo + + def getRefrenceName(self,libname,libpath): + libname = libname.replace('.lib','.xml') + library = os.path.join(libpath,libname) + + #Extracting Value from XML + libtree = ET.parse(library) + for child in libtree.iter(): + if child.tag == 'ref_model': + retVal = child.text + else: + pass + return retVal + + + diff --git a/src/kicadtoNgspice/Convert.pyc b/src/kicadtoNgspice/Convert.pyc Binary files differnew file mode 100644 index 00000000..4f80394c --- /dev/null +++ b/src/kicadtoNgspice/Convert.pyc diff --git a/src/kicadtoNgspice/DeviceModel.py b/src/kicadtoNgspice/DeviceModel.py new file mode 100644 index 00000000..a982d05f --- /dev/null +++ b/src/kicadtoNgspice/DeviceModel.py @@ -0,0 +1,357 @@ +from PyQt4 import QtGui +import os +from xml.etree import ElementTree as ET + +import TrackWidget + + +class DeviceModel(QtGui.QWidget): + """ + This class creates Device Library Tab in KicadtoNgspice Window + It dynamically creates the widget for device like diode,mosfet,transistor and jfet. + """ + + def __init__(self,schematicInfo,clarg1): + + self.clarg1=clarg1 + kicadFile = self.clarg1 + (projpath,filename)=os.path.split(kicadFile) + project_name=os.path.basename(projpath) + check=1 + try: + f=open(os.path.join(projpath,project_name+"_Previous_Values.xml"),'r') + tree=ET.parse(f) + parent_root=tree.getroot() + for child in parent_root: + if child.tag=="devicemodel": + root=child + except: + check=0 + print "Device Model Previous XML is Empty" + + + QtGui.QWidget.__init__(self) + + #Creating track widget object + self.obj_trac = TrackWidget.TrackWidget() + + #Row and column count + self.row = 0 + self.count = 1 #Entry count + self.entry_var = {} + + #For MOSFET + self.widthLabel = {} + self.lengthLabel = {} + self.multifactorLable = {} + self.devicemodel_dict_beg={} + self.devicemodel_dict_end={} + #List to hold information about device + self.deviceDetail = {} + + #Set Layout + self.grid = QtGui.QGridLayout() + self.setLayout(self.grid) + print "Reading Device model details from Schematic" + + for eachline in schematicInfo: + words = eachline.split() + if eachline[0] == 'q': + print "Device Model Transistor: ",words[0] + self.devicemodel_dict_beg[words[0]]=self.count + transbox=QtGui.QGroupBox() + transgrid=QtGui.QGridLayout() + transbox.setTitle("Add library for Transistor "+words[0]+" : "+words[4]) + self.entry_var[self.count] = QtGui.QLineEdit() + self.entry_var[self.count].setText("") + global path_name + try: + for child in root: + if child.tag[0]==eachline[0] and child.tag[1]==eachline[1]: + #print "DEVICE MODEL MATCHING---",child.tag[0],child.tag[1],eachline[0],eachline[1] + try: + if os.path.exists(child[0].text): + self.entry_var[self.count].setText(child[0].text) + path_name=child[0].text + else: + self.entry_var[self.count].setText("") + except: + print "Error when set text of device model transistor" + except: + pass + transgrid.addWidget(self.entry_var[self.count],self.row,1) + self.addbtn = QtGui.QPushButton("Add") + self.addbtn.setObjectName("%d" %self.count) + self.addbtn.clicked.connect(self.trackLibrary) + self.deviceDetail[self.count] = words[0] + if self.entry_var[self.count].text()=="": + pass + else: + self.trackLibraryWithoutButton(self.count,path_name) + transgrid.addWidget(self.addbtn,self.row,2) + transbox.setLayout(transgrid) + + #CSS + transbox.setStyleSheet(" \ + QGroupBox { border: 1px solid gray; border-radius: 9px; margin-top: 0.5em; } \ + QGroupBox::title { subcontrol-origin: margin; left: 10px; padding: 0 3px 0 3px; } \ + ") + + self.grid.addWidget(transbox) + + #Adding Device Details + + + #Increment row and widget count + self.row = self.row+1 + self.devicemodel_dict_end[words[0]]=self.count + self.count = self.count+1 + + elif eachline[0] == 'd': + print "Device Model Diode:",words[0] + self.devicemodel_dict_beg[words[0]]=self.count + diodebox=QtGui.QGroupBox() + diodegrid=QtGui.QGridLayout() + diodebox.setTitle("Add library for Diode "+words[0]+" : "+words[3]) + self.entry_var[self.count] = QtGui.QLineEdit() + self.entry_var[self.count].setText("") + #global path_name + try: + for child in root: + if child.tag[0]==eachline[0] and child.tag[1]==eachline[1]: + #print "DEVICE MODEL MATCHING---",child.tag[0],child.tag[1],eachline[0],eachline[1] + try: + if os.path.exists(child[0].text): + path_name=child[0].text + self.entry_var[self.count].setText(child[0].text) + else: + self.entry_var[self.count].setText("") + except: + print "Error when set text of device model diode" + except: + pass + diodegrid.addWidget(self.entry_var[self.count],self.row,1) + self.addbtn = QtGui.QPushButton("Add") + self.addbtn.setObjectName("%d" %self.count) + self.addbtn.clicked.connect(self.trackLibrary) + self.deviceDetail[self.count] = words[0] + if self.entry_var[self.count].text()=="": + pass + else: + self.trackLibraryWithoutButton(self.count,path_name) + diodegrid.addWidget(self.addbtn,self.row,2) + diodebox.setLayout(diodegrid) + + #CSS + diodebox.setStyleSheet(" \ + QGroupBox { border: 1px solid gray; border-radius: 9px; margin-top: 0.5em; } \ + QGroupBox::title { subcontrol-origin: margin; left: 10px; padding: 0 3px 0 3px; } \ + ") + + self.grid.addWidget(diodebox) + + #Adding Device Details + + + #Increment row and widget count + self.row = self.row+1 + self.devicemodel_dict_end[words[0]]=self.count + self.count = self.count+1 + + elif eachline[0] == 'j': + print "Device Model JFET:",words[0] + self.devicemodel_dict_beg[words[0]]=self.count + jfetbox=QtGui.QGroupBox() + jfetgrid=QtGui.QGridLayout() + jfetbox.setTitle("Add library for JFET "+words[0]+" : "+words[4]) + self.entry_var[self.count] = QtGui.QLineEdit() + self.entry_var[self.count].setText("") + #global path_name + try: + for child in root: + if child.tag[0]==eachline[0] and child.tag[1]==eachline[1]: + #print "DEVICE MODEL MATCHING---",child.tag[0],child.tag[1],eachline[0],eachline[1] + try: + if os.path.exists(child[0].text): + self.entry_var[self.count].setText(child[0].text) + path_name=child[0].text + else: + self.entry_var[self.count].setText("") + except: + print "Error when set text of Device Model JFET " + except: + pass + jfetgrid.addWidget(self.entry_var[self.count],self.row,1) + self.addbtn = QtGui.QPushButton("Add") + self.addbtn.setObjectName("%d" %self.count) + self.addbtn.clicked.connect(self.trackLibrary) + self.deviceDetail[self.count] = words[0] + if self.entry_var[self.count].text()=="": + pass + else: + self.trackLibraryWithoutButton(self.count,path_name) + jfetgrid.addWidget(self.addbtn,self.row,2) + jfetbox.setLayout(jfetgrid) + + #CSS + jfetbox.setStyleSheet(" \ + QGroupBox { border: 1px solid gray; border-radius: 9px; margin-top: 0.5em; } \ + QGroupBox::title { subcontrol-origin: margin; left: 10px; padding: 0 3px 0 3px; } \ + ") + + self.grid.addWidget(jfetbox) + + #Adding Device Details + + + #Increment row and widget count + self.row = self.row+1 + self.devicemodel_dict_end[words[0]]=self.count + self.count = self.count+1 + + + + elif eachline[0] == 'm': + self.devicemodel_dict_beg[words[0]]=self.count + mosfetbox=QtGui.QGroupBox() + mosfetgrid=QtGui.QGridLayout() + i=self.count + beg=self.count + mosfetbox.setTitle("Add library for MOSFET "+words[0]+" : "+words[5]) + self.entry_var[self.count] =QtGui.QLineEdit() + self.entry_var[self.count].setText("") + mosfetgrid.addWidget(self.entry_var[self.count],self.row,1) + self.addbtn = QtGui.QPushButton("Add") + self.addbtn.setObjectName("%d" %self.count) + self.addbtn.clicked.connect(self.trackLibrary) + mosfetgrid.addWidget(self.addbtn,self.row,2) + + #Adding Device Details + self.deviceDetail[self.count] = words[0] + + #Increment row and widget count + self.row = self.row+1 + self.count = self.count+1 + + #Adding to get MOSFET dimension + self.widthLabel[self.count] = QtGui.QLabel("Enter width of MOSFET "+words[0]+"(default=100u):") + mosfetgrid.addWidget(self.widthLabel[self.count],self.row,0) + self.entry_var[self.count] = QtGui.QLineEdit() + self.entry_var[self.count].setText("") + self.entry_var[self.count].setMaximumWidth(150) + mosfetgrid.addWidget(self.entry_var[self.count],self.row,1) + self.row = self.row + 1 + self.count = self.count+1 + + self.lengthLabel[self.count] = QtGui.QLabel("Enter length of MOSFET "+words[0]+"(default=100u):") + mosfetgrid.addWidget(self.lengthLabel[self.count],self.row,0) + self.entry_var[self.count] = QtGui.QLineEdit() + self.entry_var[self.count].setText("") + self.entry_var[self.count].setMaximumWidth(150) + mosfetgrid.addWidget(self.entry_var[self.count],self.row,1) + self.row = self.row + 1 + self.count = self.count+1 + + + self.multifactorLable[self.count] = QtGui.QLabel("Enter multiplicative factor of MOSFET "+words[0]+"(default=1):") + mosfetgrid.addWidget(self.multifactorLable[self.count],self.row,0) + self.entry_var[self.count] = QtGui.QLineEdit() + self.entry_var[self.count].setText("") + end=self.count + self.entry_var[self.count].setMaximumWidth(150) + mosfetgrid.addWidget(self.entry_var[self.count],self.row,1) + self.row = self.row + 1 + self.devicemodel_dict_end[words[0]]=self.count + self.count = self.count+1 + mosfetbox.setLayout(mosfetgrid) + #global path_name + try: + for child in root: + if child.tag[0]==eachline[0] and child.tag[1]==eachline[1]: + #print "DEVICE MODEL MATCHING---",child.tag[0],child.tag[1],eachline[0],eachline[1] + while i<=end: + self.entry_var[i].setText(child[i-beg].text) + if (i-beg)==0: + if os.path.exists(child[0].text): + self.entry_var[i].setText(child[i-beg].text) + path_name=child[i-beg].text + else: + self.entry_var[i].setText("") + i=i+1 + except: + pass + #CSS + mosfetbox.setStyleSheet(" \ + QGroupBox { border: 1px solid gray; border-radius: 9px; margin-top: 0.5em; } \ + QGroupBox::title { subcontrol-origin: margin; left: 10px; padding: 0 3px 0 3px; } \ + ") + if self.entry_var[beg].text()=="": + pass + else: + self.trackLibraryWithoutButton(beg,path_name) + self.grid.addWidget(mosfetbox) + + + self.show() + + + def trackLibrary(self): + """ + This function is use to keep track of all Device Model widget + """ + print "Calling Track Device Model Library funtion" + sending_btn = self.sender() + #print "Object Called is ",sending_btn.objectName() + self.widgetObjCount = int(sending_btn.objectName()) + + self.libfile = str(QtGui.QFileDialog.getOpenFileName(self,"Open Library Directory","../deviceModelLibrary","*.lib")) + #print "Selected Library File :",self.libfile + + #Setting Library to Text Edit Line + self.entry_var[self.widgetObjCount].setText(self.libfile) + self.deviceName = self.deviceDetail[self.widgetObjCount] + + #Storing to track it during conversion + + + if self.deviceName[0] == 'm': + width = str(self.entry_var[self.widgetObjCount+1].text()) + length = str(self.entry_var[self.widgetObjCount+2].text()) + multifactor = str(self.entry_var[self.widgetObjCount+3].text()) + if width == "" : width="100u" + if length == "": length="100u" + if multifactor == "": multifactor="1" + + self.obj_trac.deviceModelTrack[self.deviceName] = self.libfile+":"+"W="+width+" L="+length+" M="+multifactor + + else: + self.obj_trac.deviceModelTrack[self.deviceName] = self.libfile + def trackLibraryWithoutButton(self,iter_value,path_value): + """ + This function is use to keep track of all Device Model widget + """ + print "Calling Track Library function Without Button" + #print "Object Called is ",sending_btn.objectName() + self.widgetObjCount = iter_value + print "self.widgetObjCount-----",self.widgetObjCount + self.libfile = path_value + #print "Selected Library File :",self.libfile + + #Setting Library to Text Edit Line + self.entry_var[self.widgetObjCount].setText(self.libfile) + self.deviceName = self.deviceDetail[self.widgetObjCount] + + #Storing to track it during conversion + + + if self.deviceName[0] == 'm': + width = str(self.entry_var[self.widgetObjCount+1].text()) + length = str(self.entry_var[self.widgetObjCount+2].text()) + multifactor = str(self.entry_var[self.widgetObjCount+3].text()) + if width == "" : width="100u" + if length == "": length="100u" + if multifactor == "": multifactor="1" + self.obj_trac.deviceModelTrack[self.deviceName] = self.libfile+":"+"W="+width+" L="+length+" M="+multifactor + else: + self.obj_trac.deviceModelTrack[self.deviceName] = self.libfile + diff --git a/src/kicadtoNgspice/DeviceModel.pyc b/src/kicadtoNgspice/DeviceModel.pyc Binary files differnew file mode 100644 index 00000000..6ac8f337 --- /dev/null +++ b/src/kicadtoNgspice/DeviceModel.pyc diff --git a/src/kicadtoNgspice/KicadtoNgspice.py b/src/kicadtoNgspice/KicadtoNgspice.py new file mode 100644 index 00000000..4215f6f8 --- /dev/null +++ b/src/kicadtoNgspice/KicadtoNgspice.py @@ -0,0 +1,646 @@ +#=============================================================================== +# +# FILE: kicadtoNgspice.py +# +# USAGE: --- +# +# DESCRIPTION: This define all configuration used in Application. +# +# OPTIONS: --- +# REQUIREMENTS: --- +# BUGS: --- +# NOTES: --- +# AUTHOR: Fahim Khan, fahim.elex@gmail.com +# ORGANIZATION: eSim team at FOSSEE, IIT Bombay. +# CREATED: Wednesday 04 March 2015 +# REVISION: --- +#=============================================================================== +import sys +import os +from PyQt4 import QtGui +from Processing import PrcocessNetlist +import Analysis +import Source +import Model +import DeviceModel +import SubcircuitTab +import Convert +import TrackWidget + +from xml.etree import ElementTree as ET + + + +class MainWindow(QtGui.QWidget): + """ + This class create KicadtoNgspice window. + And Call Convert function if convert button is pressed. + The convert function takes all the value entered by user and create a final netlist "*.cir.out". + This final netlist is compatible with NgSpice. + """ + def __init__(self,clarg1,clarg2=None): + QtGui.QWidget.__init__(self) + + print "==================================" + print "Kicad to Ngspice netlist converter " + print "==================================" + global kicadNetlist,schematicInfo + global infoline,optionInfo + self.kicadFile = clarg1 + self.clarg1=clarg1 + self.clarg2=clarg2 + + #Create object of track widget + self.obj_track = TrackWidget.TrackWidget() + + #Clear Dictionary/List item of sub circuit and ngspice model + #Dictionary + self.obj_track.subcircuitList.clear() + self.obj_track.subcircuitTrack.clear() + self.obj_track.model_entry_var.clear() + #List + self.obj_track.modelTrack[:]=[] + + #Object of Processing + obj_proc = PrcocessNetlist() + + # Read the netlist + kicadNetlist = obj_proc.readNetlist(self.kicadFile) + + print "Given Kicad Schematic Netlist Info :",kicadNetlist + + # Construct parameter information + param = obj_proc.readParamInfo(kicadNetlist) + + # Replace parameter with values + netlist,infoline = obj_proc.preprocessNetlist(kicadNetlist,param) + + print "Schematic Info after processing Kicad Netlist: ",netlist + #print "INFOLINE",infoline + + # Separate option and schematic information + optionInfo, schematicInfo = obj_proc.separateNetlistInfo(netlist) + + print "OPTIONINFO in the Netlist",optionInfo + + #List for storing source and its value + global sourcelist, sourcelisttrack + sourcelist=[] + sourcelisttrack=[] + schematicInfo,sourcelist = obj_proc.insertSpecialSourceParam(schematicInfo,sourcelist) + + #List storing model detail + global modelList,outputOption,unknownModelList,multipleModelList,plotText + + modelList = [] + outputOption = [] + plotText = [] + schematicInfo,outputOption,modelList,unknownModelList,multipleModelList,plotText = obj_proc.convertICintoBasicBlocks(schematicInfo,outputOption,modelList,plotText) + + print "Model available in the Schematic :",modelList + + """ + Checking if any unknown model is used in schematic which is not recognized by NgSpice. + Also if the two model of same name is present under modelParamXML directory + """ + if unknownModelList: + print "Unknown Model List is : ",unknownModelList + self.msg = QtGui.QErrorMessage() + self.content = "Your schematic contain unknown model "+', '.join(unknownModelList) + self.msg.showMessage(self.content) + self.msg.setWindowTitle("Unknown Models") + + elif multipleModelList: + self.msg = QtGui.QErrorMessage() + self.mcontent = "Look like you have duplicate model in modelParamXML directory "+', '.join(multipleModelList[0]) + self.msg.showMessage(self.mcontent) + self.msg.setWindowTitle("Multiple Models") + + else: + self.createMainWindow() + + + def createMainWindow(self): + """ + This function create main window of Kicad to Ngspice converter + """ + + self.vbox = QtGui.QVBoxLayout(self) + self.hbox=QtGui.QHBoxLayout(self) + self.hbox.addStretch(1) + self.convertbtn = QtGui.QPushButton("Convert") + self.convertbtn.clicked.connect(self.callConvert) + self.hbox.addWidget(self.convertbtn) + self.vbox.addWidget(self.createcreateConvertWidget()) + self.vbox.addLayout(self.hbox) + + self.setLayout(self.vbox) + self.setWindowTitle("Kicad To NgSpice Converter") + self.show() + + def createcreateConvertWidget(self): + global obj_analysis + self.convertWindow = QtGui.QWidget() + self.analysisTab = QtGui.QScrollArea() + obj_analysis=Analysis.Analysis(self.clarg1) + self.analysisTab.setWidget(obj_analysis) + #self.analysisTabLayout = QtGui.QVBoxLayout(self.analysisTab.widget()) + self.analysisTab.setWidgetResizable(True) + global obj_source + self.sourceTab = QtGui.QScrollArea() + obj_source=Source.Source(sourcelist,sourcelisttrack,self.clarg1) + self.sourceTab.setWidget(obj_source) + #self.sourceTabLayout = QtGui.QVBoxLayout(self.sourceTab.widget()) + self.sourceTab.setWidgetResizable(True) + global obj_model + self.modelTab = QtGui.QScrollArea() + obj_model=Model.Model(schematicInfo,modelList,self.clarg1) + self.modelTab.setWidget(obj_model) + #self.modelTabLayout = QtGui.QVBoxLayout(self.modelTab.widget()) + self.modelTab.setWidgetResizable(True) + global obj_devicemodel + self.deviceModelTab = QtGui.QScrollArea() + obj_devicemodel=DeviceModel.DeviceModel(schematicInfo,self.clarg1) + self.deviceModelTab.setWidget(obj_devicemodel) + self.deviceModelTab.setWidgetResizable(True) + global obj_subcircuitTab + self.subcircuitTab = QtGui.QScrollArea() + obj_subcircuitTab = SubcircuitTab.SubcircuitTab(schematicInfo,self.clarg1) + self.subcircuitTab.setWidget(obj_subcircuitTab) + self.subcircuitTab.setWidgetResizable(True) + + self.tabWidget = QtGui.QTabWidget() + #self.tabWidget.TabShape(QtGui.QTabWidget.Rounded) + self.tabWidget.addTab(self.analysisTab,"Analysis") + self.tabWidget.addTab(self.sourceTab,"Source Details") + self.tabWidget.addTab(self.modelTab,"NgSpice Model") + self.tabWidget.addTab(self.deviceModelTab,"Device Modeling") + self.tabWidget.addTab(self.subcircuitTab,"Subcircuits") + self.mainLayout = QtGui.QVBoxLayout() + self.mainLayout.addWidget(self.tabWidget) + #self.mainLayout.addStretch(1) + self.convertWindow.setLayout(self.mainLayout) + self.convertWindow.show() + + return self.convertWindow + + def callConvert(self): + """ + Calling Convert Class Constructor + """ + global schematicInfo + global analysisoutput + global kicad + store_schematicInfo = list(schematicInfo) + (projpath,filename)=os.path.split(self.kicadFile) + project_name=os.path.basename(projpath) + + check=1 + try: + fr=open(os.path.join(projpath,project_name+"_Previous_Values.xml"),'r') + temp_tree=ET.parse(fr) + temp_root=temp_tree.getroot() + except: + check=0 + + + fw=open(os.path.join(projpath,project_name+"_Previous_Values.xml"),'w') + if check==0: + attr_parent=ET.Element("KicadtoNgspice") + if check==1: + attr_parent=temp_root + + for child in attr_parent: + if child.tag=="analysis": + attr_parent.remove(child) + + attr_analysis=ET.SubElement(attr_parent,"analysis") + attr_ac=ET.SubElement(attr_analysis,"ac") + if obj_analysis.Lin.isChecked(): + ET.SubElement(attr_ac,"field1",name="Lin").text="true" + ET.SubElement(attr_ac,"field2",name="Dec").text="false" + ET.SubElement(attr_ac,"field3",name="Oct").text="false" + elif obj_analysis.Dec.isChecked(): + ET.SubElement(attr_ac,"field1",name="Lin").text="false" + ET.SubElement(attr_ac,"field2",name="Dec").text="true" + ET.SubElement(attr_ac,"field3",name="Oct").text="false" + if obj_analysis.Oct.isChecked(): + ET.SubElement(attr_ac,"field1",name="Lin").text="false" + ET.SubElement(attr_ac,"field2",name="Dec").text="false" + ET.SubElement(attr_ac,"field3",name="Oct").text="true" + else: + pass + ET.SubElement(attr_ac,"field4",name="Start Frequency").text= str(obj_analysis.ac_entry_var[0].text()) + ET.SubElement(attr_ac,"field5",name="Stop Frequency").text= str(obj_analysis.ac_entry_var[1].text()) + ET.SubElement(attr_ac,"field6",name="No. of points").text= str(obj_analysis.ac_entry_var[2].text()) + ET.SubElement(attr_ac,"field7",name="Start Fre Combo").text= obj_analysis.ac_parameter[0] + ET.SubElement(attr_ac,"field8",name="Stop Fre Combo").text= obj_analysis.ac_parameter[1] + attr_dc=ET.SubElement(attr_analysis,"dc") + ET.SubElement(attr_dc,"field1",name="Source 1").text= str(obj_analysis.dc_entry_var[0].text()) + ET.SubElement(attr_dc,"field2",name="Start").text= str(obj_analysis.dc_entry_var[1].text()) + ET.SubElement(attr_dc,"field3",name="Increment").text= str(obj_analysis.dc_entry_var[2].text()) + ET.SubElement(attr_dc,"field4",name="Stop").text= str(obj_analysis.dc_entry_var[3].text()) + #print "OBJ_ANALYSIS.CHECK -----",self.obj_track.op_check[-1] + ET.SubElement(attr_dc,"field5",name="Operating Point").text=str(self.obj_track.op_check[-1]) + ET.SubElement(attr_dc,"field6",name="Start Combo").text= obj_analysis.dc_parameter[0] + ET.SubElement(attr_dc,"field7",name="Increment Combo").text=obj_analysis.dc_parameter[1] + ET.SubElement(attr_dc,"field8",name="Stop Combo").text= obj_analysis.dc_parameter[2] + ET.SubElement(attr_dc,"field9",name="Source 2").text= str(obj_analysis.dc_entry_var[4].text()) + ET.SubElement(attr_dc,"field10",name="Start").text= str(obj_analysis.dc_entry_var[5].text()) + ET.SubElement(attr_dc,"field11",name="Increment").text= str(obj_analysis.dc_entry_var[6].text()) + ET.SubElement(attr_dc,"field12",name="Stop").text= str(obj_analysis.dc_entry_var[7].text()) + ET.SubElement(attr_dc,"field13",name="Start Combo").text= obj_analysis.dc_parameter[3] + ET.SubElement(attr_dc,"field14",name="Increment Combo").text=obj_analysis.dc_parameter[4] + ET.SubElement(attr_dc,"field15",name="Stop Combo").text= obj_analysis.dc_parameter[5] + + + attr_tran=ET.SubElement(attr_analysis,"tran") + ET.SubElement(attr_tran,"field1",name="Start Time").text= str(obj_analysis.tran_entry_var[0].text()) + ET.SubElement(attr_tran,"field2",name="Step Time").text= str(obj_analysis.tran_entry_var[1].text()) + ET.SubElement(attr_tran,"field3",name="Stop Time").text= str(obj_analysis.tran_entry_var[2].text()) + ET.SubElement(attr_tran,"field4",name="Start Combo").text= obj_analysis.tran_parameter[0] + ET.SubElement(attr_tran,"field5",name="Step Combo").text= obj_analysis.tran_parameter[1] + ET.SubElement(attr_tran,"field6",name="Stop Combo").text= obj_analysis.tran_parameter[2] + #print "TRAN PARAMETER 2-----",obj_analysis.tran_parameter[2] + + if check==0: + attr_source=ET.SubElement(attr_parent,"source") + if check==1: + for child in attr_parent: + if child.tag=="source": + attr_source=child + count=1 + grand_child_count=1 + + for i in store_schematicInfo: + tmp_check=0 + words=i.split(' ') + wordv=words[0] + for child in attr_source: + if child.tag==wordv and child.text==words[len(words)-1]: + tmp_check=1 + for grand_child in child: + grand_child.text=str(obj_source.entry_var[grand_child_count].text()) + grand_child_count=grand_child_count+1 + grand_child_count=grand_child_count+1 + if tmp_check==0: + words=i.split(' ') + wordv=words[0] + if wordv[0]=="v" or wordv[0]=="i": + attr_var=ET.SubElement(attr_source,words[0],name="Source type") + attr_var.text=words[len(words)-1] + #ET.SubElement(attr_ac,"field1",name="Lin").text="true" + if words[len(words)-1]=="ac": + #attr_ac=ET.SubElement(attr_var,"ac") + ET.SubElement(attr_var,"field1",name="Amplitude").text=str(obj_source.entry_var[count].text()) + count=count+1 + ET.SubElement(attr_var, "field2", name = "Phase").text = str(obj_source.entry_var[count].text()) + count=count+2 + elif words[len(words)-1]=="dc": + #attr_dc=ET.SubElement(attr_var,"dc") + ET.SubElement(attr_var,"field1",name="Value").text=str(obj_source.entry_var[count].text()) + count=count+2 + elif words[len(words)-1]=="sine": + #attr_sine=ET.SubElement(attr_var,"sine") + ET.SubElement(attr_var,"field1",name="Offset Value").text=str(obj_source.entry_var[count].text()) + count=count+1 + ET.SubElement(attr_var,"field2",name="Amplitude").text=str(obj_source.entry_var[count].text()) + count=count+1 + ET.SubElement(attr_var,"field3",name="Frequency").text=str(obj_source.entry_var[count].text()) + count=count+1 + ET.SubElement(attr_var,"field4",name="Delay Time").text=str(obj_source.entry_var[count].text()) + count=count+1 + ET.SubElement(attr_var,"field5",name="Damping Factor").text=str(obj_source.entry_var[count].text()) + count=count+2 + elif words[len(words)-1]=="pulse": + #attr_pulse=ET.SubElement(attr_var,"pulse") + ET.SubElement(attr_var,"field1",name="Initial Value").text=str(obj_source.entry_var[count].text()) + count=count+1 + ET.SubElement(attr_var,"field2",name="Pulse Value").text=str(obj_source.entry_var[count].text()) + count=count+1 + ET.SubElement(attr_var,"field3",name="Delay Time").text=str(obj_source.entry_var[count].text()) + count=count+1 + ET.SubElement(attr_var,"field4",name="Rise Time").text=str(obj_source.entry_var[count].text()) + count=count+1 + ET.SubElement(attr_var,"field5",name="Fall Time").text=str(obj_source.entry_var[count].text()) + count=count+1 + ET.SubElement(attr_var,"field5",name="Pulse width").text=str(obj_source.entry_var[count].text()) + count=count+1 + ET.SubElement(attr_var,"field5",name="Period").text=str(obj_source.entry_var[count].text()) + count=count+2 + elif words[len(words)-1]=="pwl": + #attr_pwl=ET.SubElement(attr_var,"pwl") + ET.SubElement(attr_var,"field1",name="Enter in pwl format").text=str(obj_source.entry_var[count].text()) + count=count+2 + elif words[len(words)-1]=="exp": + #attr_exp=ET.SubElement(attr_var,"exp") + ET.SubElement(attr_var,"field1",name="Initial Value").text=str(obj_source.entry_var[count].text()) + count=count+1 + ET.SubElement(attr_var,"field2",name="Pulsed Value").text=str(obj_source.entry_var[count].text()) + count=count+1 + ET.SubElement(attr_var,"field3",name="Rise Delay Time").text=str(obj_source.entry_var[count].text()) + count=count+1 + ET.SubElement(attr_var,"field4",name="Rise Time Constant").text=str(obj_source.entry_var[count].text()) + count=count+1 + ET.SubElement(attr_var,"field5",name="Fall TIme").text=str(obj_source.entry_var[count].text()) + count=count+1 + ET.SubElement(attr_var,"field6",name="Fall Time Constant").text=str(obj_source.entry_var[count].text()) + count=count+2 + else: + pass + + + if check==0: + attr_model=ET.SubElement(attr_parent,"model") + if check==1: + for child in attr_parent: + if child.tag=="model": + attr_model=child + i=0 + #tmp_check is a variable to check for duplicates in the xml file + tmp_check=0 + #tmp_i is the iterator in case duplicates are there; then in that case we need to replace only the child node and not create a new parent node + + for line in modelList: + tmp_check=0 + for rand_itr in obj_model.obj_trac.modelTrack: + if rand_itr[2]==line[2] and rand_itr[3]==line[3]: + start=rand_itr[7] + end=rand_itr[8] + i=start + for child in attr_model: + if child.text==line[2] and child.tag==line[3]: + for grand_child in child: + if i<=end: + grand_child.text=str(obj_model.obj_trac.model_entry_var[i].text()) + i=i+1 + else: + pass + tmp_check=1 + + if tmp_check==0: + attr_ui=ET.SubElement(attr_model,line[3],name="type") + attr_ui.text=line[2] + for key,value in line[7].iteritems(): + if hasattr(value, '__iter__') and i<=end: + for item in value: + ET.SubElement(attr_ui,"field"+str(i+1),name=item).text=str(obj_model.obj_trac.model_entry_var[i].text()) + i=i+1 + + else: + ET.SubElement(attr_ui,"field"+str(i+1),name=value).text=str(obj_model.obj_trac.model_entry_var[i].text()) + + i=i+1 + + if check==0: + attr_devicemodel=ET.SubElement(attr_parent,"devicemodel") + if check==1: + for child in attr_parent: + if child.tag=="devicemodel": + del child[:] + attr_devicemodel=child + + + for i in obj_devicemodel.devicemodel_dict_beg: + attr_var=ET.SubElement(attr_devicemodel,i) + it=obj_devicemodel.devicemodel_dict_beg[i] + end=obj_devicemodel.devicemodel_dict_end[i] + while it<=end: + ET.SubElement(attr_var,"field").text=str(obj_devicemodel.entry_var[it].text()) + it=it+1 + + if check==0: + attr_subcircuit=ET.SubElement(attr_parent,"subcircuit") + if check==1: + for child in attr_parent: + if child.tag=="subcircuit": + del child[:] + attr_subcircuit=child + + for i in obj_subcircuitTab.subcircuit_dict_beg: + attr_var=ET.SubElement(attr_subcircuit,i) + it=obj_subcircuitTab.subcircuit_dict_beg[i] + end=obj_subcircuitTab.subcircuit_dict_end[i] + + while it<=end: + ET.SubElement(attr_var,"field").text=str(obj_subcircuitTab.entry_var[it].text()) + it=it+1 + + + tree=ET.ElementTree(attr_parent) + tree.write(fw) + + + self.obj_convert = Convert.Convert(self.obj_track.sourcelisttrack["ITEMS"], + self.obj_track.source_entry_var["ITEMS"], + store_schematicInfo,self.clarg1) + + try: + #Adding Source Value to Schematic Info + store_schematicInfo = self.obj_convert.addSourceParameter() + print "Netlist After Adding Source details :",store_schematicInfo + + #Adding Model Value to store_schematicInfo + store_schematicInfo = self.obj_convert.addModelParameter(store_schematicInfo) + print "Netlist After Adding Ngspice Model :",store_schematicInfo + + #Adding Device Library to SchematicInfo + store_schematicInfo = self.obj_convert.addDeviceLibrary(store_schematicInfo,self.kicadFile) + print "Netlist After Adding Device Model Library :",store_schematicInfo + + #Adding Subcircuit Library to SchematicInfo + store_schematicInfo = self.obj_convert.addSubcircuit(store_schematicInfo, self.kicadFile) + print "Netlist After Adding subcircuits :",store_schematicInfo + + analysisoutput = self.obj_convert.analysisInsertor(self.obj_track.AC_entry_var["ITEMS"], + self.obj_track.DC_entry_var["ITEMS"], + self.obj_track.TRAN_entry_var["ITEMS"], + self.obj_track.set_CheckBox["ITEMS"], + self.obj_track.AC_Parameter["ITEMS"], + self.obj_track.DC_Parameter["ITEMS"], + self.obj_track.TRAN_Parameter["ITEMS"], + self.obj_track.AC_type["ITEMS"], + self.obj_track.op_check) + + print "Analysis OutPut ",analysisoutput + + #Calling netlist file generation function + self.createNetlistFile(store_schematicInfo,plotText) + + self.msg = "The Kicad to Ngspice Conversion completed successfully!!!!!!" + QtGui.QMessageBox.information(self, "Information", self.msg, QtGui.QMessageBox.Ok) + + except Exception as e: + print "Exception Message: ",e + print "There was error while converting kicad to ngspice" + self.close() + + # Generate .sub file from .cir.out file if it is a subcircuit + subPath = os.path.splitext(self.kicadFile)[0] + + if self.clarg2 == "sub": + self.createSubFile(subPath) + + def createNetlistFile(self,store_schematicInfo,plotText): + print "Creating Final netlist" + #print "INFOLINE",infoline + #print "OPTIONINFO",optionInfo + #print "Device MODEL LIST ",devicemodelList + #print "SUBCKT ",subcktList + #print "OUTPUTOPTION",outputOption + #print "KicadfIle",kicadFile + store_optionInfo = list(optionInfo) #To avoid writing optionInfo twice in final netlist + + #checking if analysis files is present + (projpath,filename) = os.path.split(self.kicadFile) + analysisFileLoc = os.path.join(projpath,"analysis") + #print "Analysis File Location",analysisFileLoc + if os.path.exists(analysisFileLoc): + try: + f = open(analysisFileLoc) + #Read data + data = f.read() + # Close the file + f.close() + + except : + print "Error While opening Project Analysis file. Please check it" + sys.exit() + else: + print analysisFileLoc + " does not exist" + sys.exit() + + #Adding analysis file info to optionInfo + analysisData=data.splitlines() + for eachline in analysisData: + eachline=eachline.strip() + if len(eachline)>1: + if eachline[0]=='.': + store_optionInfo.append(eachline) + else: + pass + + #print "Option Info",optionInfo + analysisOption = [] + initialCondOption=[] + simulatorOption =[] + #includeOption=[] #Don't know why to use it + #model = [] #Don't know why to use it + + for eachline in store_optionInfo: + words=eachline.split() + option=words[0] + if (option=='.ac' or option=='.dc' or option=='.disto' or option=='.noise' or + option=='.op' or option=='.pz' or option=='.sens' or option=='.tf' or + option=='.tran'): + analysisOption.append(eachline+'\n') + + elif (option=='.save' or option=='.print' or option=='.plot' or option=='.four'): + eachline=eachline.strip('.') + outputOption.append(eachline+'\n') + elif (option=='.nodeset' or option=='.ic'): + initialCondOption.append(eachline+'\n') + elif option=='.option': + simulatorOption.append(eachline+'\n') + #elif (option=='.include' or option=='.lib'): + # includeOption.append(eachline+'\n') + #elif (option=='.model'): + # model.append(eachline+'\n') + elif option=='.end': + continue; + + + #Start creating final netlist cir.out file + outfile = self.kicadFile+".out" + out=open(outfile,"w") + out.writelines(infoline) + out.writelines('\n') + sections=[simulatorOption, initialCondOption, store_schematicInfo, analysisOption] + + for section in sections: + if len(section) == 0: + continue + else: + for line in section: + out.writelines('\n') + out.writelines(line) + + out.writelines('\n* Control Statements \n') + out.writelines('.control\n') + out.writelines('run\n') + #out.writelines(outputOption) + out.writelines('print allv > plot_data_v.txt\n') + out.writelines('print alli > plot_data_i.txt\n') + for item in plotText: + out.writelines(item+'\n') + out.writelines('.endc\n') + out.writelines('.end\n') + out.close() + + + + def createSubFile(self,subPath): + self.project = subPath + self.projName = os.path.basename(self.project) + if os.path.exists(self.project+".cir.out"): + try: + f = open(self.project+".cir.out") + except : + print("Error in opening .cir.out file.") + else: + print self.projName + ".cir.out does not exist. Please create a spice netlist." + + # Read the data from file + data=f.read() + # Close the file + + f.close() + newNetlist=[] + netlist=iter(data.splitlines()) + for eachline in netlist: + eachline=eachline.strip() + if len(eachline)<1: + continue + words=eachline.split() + if eachline[2] == 'u': + if words[len(words)-1] == "port": + subcktInfo = ".subckt "+self.projName+" " + for i in range(2,len(words)-1): + subcktInfo+=words[i]+" " + continue + if words[0] == ".end" or words[0] == ".ac" or words[0] == ".dc" or words[0] == ".tran" or words[0] == '.disto' or words[0] == '.noise' or words[0] == '.op' or words[0] == '.pz' or words[0] == '.sens' or words[0] == '.tf': + continue + elif words[0] == ".control": + while words[0] != ".endc": + eachline=netlist.next() + eachline=eachline.strip() + if len(eachline)<1: + continue + words=eachline.split() + else: + newNetlist.append(eachline) + + outfile=self.project+".sub" + out=open(outfile,"w") + out.writelines("* Subcircuit " + self.projName) + out.writelines('\n') + out.writelines(subcktInfo) + out.writelines('\n') + + for i in range(len(newNetlist),0,-1): + newNetlist.insert(i,'\n') + + out.writelines(newNetlist) + out.writelines('\n') + + out.writelines('.ends ' + self.projName) + print "The subcircuit has been written in "+self.projName+".sub" + + + + + + + + +
\ No newline at end of file diff --git a/src/kicadtoNgspice/KicadtoNgspice.pyc b/src/kicadtoNgspice/KicadtoNgspice.pyc Binary files differnew file mode 100644 index 00000000..ecfae361 --- /dev/null +++ b/src/kicadtoNgspice/KicadtoNgspice.pyc diff --git a/src/kicadtoNgspice/Model.py b/src/kicadtoNgspice/Model.py new file mode 100644 index 00000000..25a23d8c --- /dev/null +++ b/src/kicadtoNgspice/Model.py @@ -0,0 +1,140 @@ + +from PyQt4 import QtGui + +import TrackWidget +from xml.etree import ElementTree as ET +import os + + +class Model(QtGui.QWidget): + """ + This class creates Model Tab of KicadtoNgspice window. + The widgets are created dynamically in the Model Tab. + """ + + def __init__(self,schematicInfo,modelList,clarg1): + + QtGui.QWidget.__init__(self) + + #Processing for getting previous values + kicadFile = clarg1 + (projpath,filename)=os.path.split(kicadFile) + project_name=os.path.basename(projpath) + check=1 + try: + f=open(os.path.join(projpath,project_name+"_Previous_Values.xml"),'r') + tree=ET.parse(f) + parent_root=tree.getroot() + for child in parent_root: + if child.tag=="model": + root=child + except: + check=0 + print "Model Previous Values XML is Empty" + + + + #Creating track widget object + self.obj_trac = TrackWidget.TrackWidget() + + #for increasing row and counting/tracking line edit widget + self.nextrow = 0 + self.nextcount = 0 + + #for storing line edit details position details + self.start = 0 + self.end = 0 + + #Creating GUI dynamically for Model tab + self.grid = QtGui.QGridLayout() + self.setLayout(self.grid) + + for line in modelList: + #print "ModelList Item:",line + #Adding title label for model + #Key: Tag name,Value:Entry widget number + tag_dict = {} + modelbox=QtGui.QGroupBox() + modelgrid=QtGui.QGridLayout() + modelbox.setTitle(line[5]) + self.start=self.nextcount + #line[7] is parameter dictionary holding parameter tags. + i=0 + for key,value in line[7].iteritems(): + #print "Key : ",key + #print "Value : ",value + #Check if value is iterable + if hasattr(value, '__iter__'): + #For tag having vector value + temp_tag = [] + for item in value: + paramLabel = QtGui.QLabel(item) + modelgrid.addWidget(paramLabel,self.nextrow,0) + self.obj_trac.model_entry_var[self.nextcount]= QtGui.QLineEdit() + modelgrid.addWidget(self.obj_trac.model_entry_var[self.nextcount],self.nextrow,1) + try: + for child in root: + if child.text==line[2] and child.tag==line[3]: + self.obj_trac.model_entry_var[self.nextcount].setText(child[i].text) + i=i+1 + except: + pass + temp_tag.append(self.nextcount) + self.nextcount = self.nextcount+1 + self.nextrow = self.nextrow+1 + tag_dict[key] = temp_tag + else: + paramLabel = QtGui.QLabel(value) + modelgrid.addWidget(paramLabel,self.nextrow,0) + self.obj_trac.model_entry_var[self.nextcount]= QtGui.QLineEdit() + modelgrid.addWidget(self.obj_trac.model_entry_var[self.nextcount],self.nextrow,1) + try: + for child in root: + if child.text==line[2] and child.tag==line[3]: + self.obj_trac.model_entry_var[self.nextcount].setText(child[i].text) + i=i+1 + except: + pass + tag_dict[key] = self.nextcount + self.nextcount = self.nextcount+1 + self.nextrow = self.nextrow+1 + self.end= self.nextcount-1 + #print "End",self.end + modelbox.setLayout(modelgrid) + + #CSS + modelbox.setStyleSheet(" \ + QGroupBox { border: 1px solid gray; border-radius: 9px; margin-top: 0.5em; } \ + QGroupBox::title { subcontrol-origin: margin; left: 10px; padding: 0 3px 0 3px; } \ + ") + + self.grid.addWidget(modelbox) + + ''' + Listing all + line[0] = index + line[1] = compLine + line[2] = modelname #Change from compType to modelname + line[3] = compName + line[4] = comment + line[5] = title + line[6] = type i.e analog or digital + Now adding start,end and tag_dict which will be line[7],line[8] and line[9] respectively + ''' + + #This keeps the track of Model Tab Widget + lst=[line[0],line[1],line[2],line[3],line[4],line[5],line[6],self.start,self.end,tag_dict] + check=0 + for itr in self.obj_trac.modelTrack: + if itr==lst: + check=1 + + if check==0: + self.obj_trac.modelTrack.append(lst) + + #print "The tag dictionary : ",tag_dict + + + + self.show() + diff --git a/src/kicadtoNgspice/Model.pyc b/src/kicadtoNgspice/Model.pyc Binary files differnew file mode 100644 index 00000000..0d93058f --- /dev/null +++ b/src/kicadtoNgspice/Model.pyc diff --git a/src/kicadtoNgspice/Processing.py b/src/kicadtoNgspice/Processing.py new file mode 100644 index 00000000..09544f19 --- /dev/null +++ b/src/kicadtoNgspice/Processing.py @@ -0,0 +1,380 @@ +import sys +import os +from xml.etree import ElementTree as ET + + + +class PrcocessNetlist: + """ + This class include all the function required for pre-proccessing of netlist + before converting to Ngspice Netlist. + """ + modelxmlDIR = '../modelParamXML' + def __init__(self): + pass + + def readNetlist(self,filename): + f = open(filename) + data=f.read() + f.close() + return data.splitlines() + + def readParamInfo(self,kicadNetlis): + """Read Parameter information and store it into dictionary""" + param={} + for eachline in kicadNetlis: + print eachline + eachline=eachline.strip() + if len(eachline)>1: + words=eachline.split() + option=words[0].lower() + if option=='.param': + for i in range(1, len(words), 1): + paramList=words[i].split('=') + param[paramList[0]]=paramList[1] + return param + + def preprocessNetlist(self,kicadNetlis,param): + """Preprocess netlist (replace parameters)""" + netlist=[] + for eachline in kicadNetlis: + # Remove leading and trailing blanks spaces from line + eachline=eachline.strip() + # Remove special character $ + eachline=eachline.replace('$','') + # Replace parameter with values + for subParam in eachline.split(): + if '}' in subParam: + key=subParam.split()[0] + key=key.strip('{') + key=key.strip('}') + if key in param: + eachline=eachline.replace('{'+key+'}',param[key]) + else: + print "Parameter " + key +" does not exists" + value=raw_input('Enter parameter value: ') + eachline=eachline.replace('{'+key+'}',value) + #Convert netlist into lower case letter + eachline=eachline.lower() + # Construct netlist + if len(eachline)>1: + if eachline[0]=='+': + netlist.append(netlist.pop()+eachline.replace('+',' ')) + else: + netlist.append(eachline) + #Copy information line + infoline=netlist[0] + netlist.remove(netlist[0]) + return netlist,infoline + + def separateNetlistInfo(self,netlist): + optionInfo=[] + schematicInfo=[] + for eachline in netlist: + if eachline[0]=='*': + continue + elif eachline[0]=='.': + optionInfo.append(eachline) + else: + schematicInfo.append(eachline) + return optionInfo,schematicInfo + + + def insertSpecialSourceParam(self,schematicInfo,sourcelist): + #Inser Special source parameter + schematicInfo1=[] + + print "Reading schematic info for source details" + + for compline in schematicInfo: + words=compline.split() + compName=words[0] + # Ask for parameters of source + if compName[0]=='v' or compName[0]=='i': + # Find the index component from circuit + index=schematicInfo.index(compline) + if words[3]=="pulse": + Title="Add parameters for pulse source "+compName + v1=' Enter initial value(Volts/Amps): ' + v2=' Enter pulsed value(Volts/Amps): ' + td=' Enter delay time (seconds): ' + tr=' Enter rise time (seconds): ' + tf=' Enter fall time (seconds): ' + pw=' Enter pulse width (seconds): ' + tp=' Enter period (seconds): ' + sourcelist.append([index,compline,words[3],Title,v1,v2,td,tr,tf,pw,tp]) + + elif words[3]=="sine": + Title="Add parameters for sine source "+compName + vo=' Enter offset value (Volts/Amps): ' + va=' Enter amplitude (Volts/Amps): ' + freq=' Enter frequency (Hz): ' + td=' Enter delay time (seconds): ' + theta=' Enter damping factor (1/seconds): ' + sourcelist.append([index,compline,words[3],Title,vo,va,freq,td,theta]) + + elif words[3]=="pwl": + Title="Add parameters for pwl source "+compName + t_v=' Enter in pwl format without bracket i.e t1 v1 t2 v2.... ' + sourcelist.append([index,compline,words[3],Title,t_v]) + + elif words[3]=="ac": + Title="Add parameters for ac source "+compName + v_a=' Enter amplitude (Volts/Amps): ' + p_a =' Enter Phase Shift: ' + sourcelist.append([index,compline,words[3],Title,v_a,p_a]) + + elif words[3]=="exp": + Title="Add parameters for exponential source "+compName + v1=' Enter initial value(Volts/Amps): ' + v2=' Enter pulsed value(Volts/Amps): ' + td1=' Enter rise delay time (seconds): ' + tau1=' Enter rise time constant (seconds): ' + td2=' Enter fall time (seconds): ' + tau2=' Enter fall time constant (seconds): ' + sourcelist.append([index,compline,words[3],Title,v1,v2,td1,tau1,td2,tau2]) + + elif words[3]=="dc": + Title="Add parameters for DC source "+compName + v1=' Enter value(Volts/Amps): ' + v2=' Enter zero frequency: ' + sourcelist.append([index,compline,words[3],Title,v1,v2]) + + elif compName[0]=='h' or compName[0]=='f': + # Find the index component from the circuit + index=schematicInfo.index(compline) + schematicInfo.remove(compline) + schematicInfo.insert(index,"* "+compName) + schematicInfo1.append("V"+compName+" "+words[3]+" "+words[4]+" 0") + schematicInfo1.append(compName+" "+words[1]+" "+words[2]+" "+"V"+compName+" "+words[5]) + + schematicInfo=schematicInfo+schematicInfo1 + print "Source List : ",sourcelist + #print schematicInfo + return schematicInfo,sourcelist + + + def convertICintoBasicBlocks(self,schematicInfo,outputOption,modelList,plotText): + print "Reading Schematic info for Model" + #Insert details of Ngspice model + unknownModelList = [] + multipleModelList = [] + plotList = ['plot_v1','plot_v2','plot_i2','plot_log','plot_db','plot_phase'] + interMediateNodeCount=1 + k = 1 + for compline in schematicInfo: + words = compline.split() + compName = words[0] + #print "Compline----------------->",compline + #print "compName-------------->",compName + # Find the IC from schematic + if compName[0]=='u' or compName[0] == 'U': + # Find the component from the circuit + index=schematicInfo.index(compline) + compType=words[len(words)-1]; + schematicInfo.remove(compline) + paramDict = {} + #e.g compLine : u1 1 2 gain + #compType : gain + #compName : u1 + #print "Compline",compline + #print "CompType",compType + #print "Words",words + #print "compName",compName + #Looking if model file is present + if compType != "port" and compType != "ic" and compType not in plotList and compType != 'transfo': + xmlfile = compType+".xml" #XML Model File + count = 0 #Check if model of same name is present + modelPath = [] + all_dir = [x[0] for x in os.walk(PrcocessNetlist.modelxmlDIR)] + for each_dir in all_dir: + all_file = os.listdir(each_dir) + if xmlfile in all_file: + count += 1 + modelPath.append(os.path.join(each_dir,xmlfile)) + + if count > 1: + multipleModelList.append(modelPath) + elif count == 0: + unknownModelList.append(compType) + elif count == 1: + try: + print "Start Parsing Previous Values XML for ngspice model :",modelPath + tree = ET.parse(modelPath[0]) + + root = tree.getroot() + #Getting number of nodes for model and title + for child in tree.iter(): + if child.tag == 'node_number': + num_of_nodes = int(child.text) + elif child.tag == 'title': + title = child.text+" "+compName + elif child.tag == 'name': + modelname = child.text + elif child.tag == 'type': + #Checking for Analog and Digital + type = child.text + elif child.tag == 'split': + splitDetail = child.text + + + for param in tree.findall('param'): + for item in param: + #print "Tags ",item.tag + #print "Value",item.text + if 'vector'in item.attrib: + #print "Tag having vector attribute",item.tag,item.attrib['vector'] + temp_count = 1 + temp_list = [] + for i in range(0,int(item.attrib['vector'])): + temp_list.append(item.text+" "+str(temp_count)) + temp_count += 1 + if 'default' in item.attrib: + paramDict[item.tag+":"+item.attrib['default']] = temp_list + else: + paramDict[item.tag] = item.text + + else: + if 'default' in item.attrib: + paramDict[item.tag+":"+item.attrib['default']] = item.text + else: + paramDict[item.tag] = item.text + + + #print "Number of Nodes : ",num_of_nodes + #print "Title : ",title + #print "Parameters",paramDict + #Creating line for adding model line in schematic + if splitDetail == 'None': + modelLine = "a"+str(k)+" " + for i in range(1,num_of_nodes+1): + modelLine += words[i]+" " + modelLine += compName + + else: + print "Split Details :",splitDetail + modelLine = "a"+str(k)+" " + vectorDetail = splitDetail.split(':') + #print "Vector Details",vectorDetail + pos = 1 #Node position + for item in vectorDetail: + try: + if item.split("-")[1] == 'V': + #print "Vector" + if compType == "aswitch": + modelLine += "(" + for i in range(0,int(item.split("-")[0])): + modelLine += words[pos]+" " + pos += 1 + modelLine += ") " + else: + modelLine += "[" + for i in range(0,int(item.split("-")[0])): + modelLine += words[pos]+" " + pos += 1 + modelLine += "] " + elif item.split("-")[1] == 'NV': + #print "Non Vector" + for i in range(0,int(item.split("-")[0])): + modelLine += words[pos]+" " + pos += 1 + + except: + print "There is error while processing Vector Details" + sys.exit(2) + modelLine += compName + + #print "Final Model Line :",modelLine + try: + schematicInfo.append(modelLine) + k=k+1 + except Exception as e: + print "Error while appending ModelLine ",modelLine + print "Exception Message : ",str(e) + #Insert comment at remove line + schematicInfo.insert(index,"* "+compline) + comment = "* Schematic Name: "+compType+", NgSpice Name: "+modelname + #Here instead of adding compType(use for XML), added modelName(Unique Model Name) + modelList.append([index,compline,modelname,compName,comment,title,type,paramDict]) + except Exception as e: + print "Unable to parse the model, Please check your your XML file" + print "Exception Message : ",str(e) + sys.exit(2) + elif compType == "ic": + schematicInfo.insert(index,"* "+compline) + modelname = "ic" + comment = "* "+compline + title = "Initial Condition for "+compName + type = "NA" #Its is not model + text = "Enter initial voltage at node for "+compline + paramDict[title] = text + modelList.append([index,compline,modelname,compName,comment,title,type,paramDict]) + + elif compType in plotList: + schematicInfo.insert(index,"* "+compline) + if compType == 'plot_v1': + words = compline.split() + plotText.append("plot v("+words[1]+")") + elif compType == 'plot_v2': + words = compline.split() + plotText.append("plot v("+words[1]+","+words[2]+")") + elif compType == 'plot_i2': + words = compline.split() + #Adding zero voltage source to netlist + schematicInfo.append("v_"+words[0]+" "+words[1]+" "+words[2]+" "+"0") + plotText.append("plot i(v_"+words[0]+")") + elif compType == 'plot_log': + words = compline.split() + plotText.append("plot log("+words[1]+")") + elif compType == 'plot_db': + words = compline.split() + plotText.append("plot db("+words[1]+")") + elif compType == 'plot_phase': + words = compline.split() + plotText.append("plot phase("+words[1]+")") + + elif compType == 'transfo': + schematicInfo.insert(index,"* "+compline) + + #For Primary Couple + modelLine = "a"+str(k)+" ("+words[1]+" "+words[2]+") (interNode_"+str(interMediateNodeCount)+" "+words[3]+") " + modelLine += compName+"_primary" + schematicInfo.append(modelLine) + k=k+1 + #For iron core + modelLine = "a"+str(k)+" ("+words[4]+" "+words[2]+") (interNode_"+str(interMediateNodeCount+1)+" "+words[3]+") " + modelLine += compName+"_secondary" + schematicInfo.append(modelLine) + k=k+1 + #For Secondary Couple + modelLine = "a"+str(k)+" (interNode_"+str(interMediateNodeCount)+" interNode_"+str(interMediateNodeCount+1)+") " + modelLine += compName+"_iron_core" + schematicInfo.append(modelLine) + k=k+1 + interMediateNodeCount += 2 + + modelname = "transfo" + comment = "* "+compline + title = "Transformer details for model "+compName + type = "NA" #It is model but do not load from xml and lib file + paramDict['h1_array'] = "Enter the H1 array " + paramDict['primary_turns'] = "Enter the primary number of turns (default=310) " + paramDict['area'] = "Enter iron core area (default=1)" + paramDict['secondar_turns'] = "Enter the secondary number of turns (default=620)" + paramDict['length'] = "Enter iron core length (default=0.01)" + paramDict['b1_array'] = "Enter the B1 array " + + + modelList.append([index,compline,modelname,compName,comment,title,type,paramDict]) + + else: + schematicInfo.insert(index,"* "+compline) + + print "UnknownModelList Used in the Schematic",unknownModelList + print "Multiple Model XML file with same name ",multipleModelList + print "Model List Details : ",modelList + + return schematicInfo,outputOption,modelList,unknownModelList,multipleModelList,plotText + + + diff --git a/src/kicadtoNgspice/Processing.pyc b/src/kicadtoNgspice/Processing.pyc Binary files differnew file mode 100644 index 00000000..92c86492 --- /dev/null +++ b/src/kicadtoNgspice/Processing.pyc diff --git a/src/kicadtoNgspice/Source.py b/src/kicadtoNgspice/Source.py new file mode 100644 index 00000000..1cf1487d --- /dev/null +++ b/src/kicadtoNgspice/Source.py @@ -0,0 +1,305 @@ +import os +from PyQt4 import QtGui +import TrackWidget +from xml.etree import ElementTree as ET + +class Source(QtGui.QWidget): + """ + This class create Source Tab of KicadtoNgSpice Window. + """ + + def __init__(self,sourcelist,sourcelisttrack,clarg1): + QtGui.QWidget.__init__(self) + self.obj_track = TrackWidget.TrackWidget() + #Variable + self.count = 1 + self.clarg1=clarg1 + self.start = 0 + self.end = 0 + self.row = 0 + self.entry_var = {} + #self.font = QtGui.QFont("Times",20,QtGui.QFont.Bold,True) + + #Creating Source Widget + self.createSourceWidget(sourcelist,sourcelisttrack) + + + + def createSourceWidget(self,sourcelist,sourcelisttrack): + """ + This function dynamically create source widget in the Source tab of KicadtoNgSpice window + """ + kicadFile = self.clarg1 + (projpath,filename)=os.path.split(kicadFile) + project_name=os.path.basename(projpath) + check=1 + try: + f=open(os.path.join(projpath,project_name+"_Previous_Values.xml"),'r') + tree=ET.parse(f) + parent_root=tree.getroot() + for child in parent_root: + if child.tag=="source": + root=child + except: + check=0 + print "Source Previous Values XML is Empty" + + self.grid = QtGui.QGridLayout() + self.setLayout(self.grid) + xml_num=0 + + if sourcelist: + for line in sourcelist: + #print "Voltage source line index: ",line[0] + print "SourceList line: ",line + track_id=line[0] + #print "track_id is ",track_id + if line[2]=='ac': + acbox=QtGui.QGroupBox() + acbox.setTitle(line[3]) + acgrid=QtGui.QGridLayout() + self.start=self.count + label1=QtGui.QLabel(line[4]) + label2 = QtGui.QLabel(line[5]) + acgrid.addWidget(label1,self.row,0) + acgrid.addWidget(label2, self.row+1, 0) + self.entry_var[self.count]=QtGui.QLineEdit() + self.entry_var[self.count].setMaximumWidth(150) + acgrid.addWidget(self.entry_var[self.count],self.row,1) + self.entry_var[self.count+1]=QtGui.QLineEdit() + self.entry_var[self.count+1].setMaximumWidth(150) + acgrid.addWidget(self.entry_var[self.count+1],self.row+1,1) + self.entry_var[self.count].setText("") + self.entry_var[self.count+1].setText("") + try: + for child in root: + templist1=line[1] + templist2=templist1.split(' ') + + if child.tag==templist2[0] and child.text==line[2]: + self.entry_var[self.count].setText(child[0].text) + self.entry_var[self.count+1].setText(child[1].text) + except: + pass + #Value Need to check previuouse value + #self.entry_var[self.count].setText("") + self.row=self.row+1 + self.end=self.count+1 + self.count=self.count+1 + acbox.setLayout(acgrid) + + #CSS + acbox.setStyleSheet(" \ + QGroupBox { border: 1px solid gray; border-radius: 9px; margin-top: 0.5em; } \ + QGroupBox::title { subcontrol-origin: margin; left: 10px; padding: 0 3px 0 3px; } \ + ") + + self.grid.addWidget(acbox) + sourcelisttrack.append([track_id,'ac',self.start,self.end]) + + + elif line[2]=='dc': + dcbox=QtGui.QGroupBox() + dcbox.setTitle(line[3]) + dcgrid=QtGui.QGridLayout() + self.row=self.row+1 + self.start=self.count + label=QtGui.QLabel(line[4]) + dcgrid.addWidget(label,self.row,0) + self.entry_var[self.count]=QtGui.QLineEdit() + self.entry_var[self.count].setMaximumWidth(150) + dcgrid.addWidget(self.entry_var[self.count],self.row,1) + self.entry_var[self.count].setText("") + try: + for child in root: + templist1=line[1] + templist2=templist1.split(' ') + + if child.tag==templist2[0] and child.text==line[2]: + self.entry_var[self.count].setText(child[0].text) + except: + pass + + self.row=self.row+1 + self.end=self.count + self.count=self.count+1 + dcbox.setLayout(dcgrid) + + #CSS + dcbox.setStyleSheet(" \ + QGroupBox { border: 1px solid gray; border-radius: 9px; margin-top: 0.5em; } \ + QGroupBox::title { subcontrol-origin: margin; left: 10px; padding: 0 3px 0 3px; } \ + ") + + self.grid.addWidget(dcbox) + sourcelisttrack.append([track_id,'dc',self.start,self.end]) + + elif line[2]=='sine': + sinebox=QtGui.QGroupBox() + sinebox.setTitle(line[3]) + sinegrid=QtGui.QGridLayout() + self.row=self.row+1 + self.start=self.count + + for it in range(4,9): + label=QtGui.QLabel(line[it]) + sinegrid.addWidget(label,self.row,0) + self.entry_var[self.count]=QtGui.QLineEdit() + self.entry_var[self.count].setMaximumWidth(150) + sinegrid.addWidget(self.entry_var[self.count],self.row,1) + self.entry_var[self.count].setText("") + try: + for child in root: + templist1=line[1] + templist2=templist1.split(' ') + if child.tag==templist2[0] and child.text==line[2]: + self.entry_var[self.count].setText(child[it-4].text) + except: + pass + + + self.row=self.row+1 + self.count=self.count+1 + self.end=self.count-1 + sinebox.setLayout(sinegrid) + + #CSS + sinebox.setStyleSheet(" \ + QGroupBox { border: 1px solid gray; border-radius: 9px; margin-top: 0.5em; } \ + QGroupBox::title { subcontrol-origin: margin; left: 10px; padding: 0 3px 0 3px; } \ + ") + + self.grid.addWidget(sinebox) + sourcelisttrack.append([track_id,'sine',self.start,self.end]) + + elif line[2]=='pulse': + pulsebox=QtGui.QGroupBox() + pulsebox.setTitle(line[3]) + pulsegrid=QtGui.QGridLayout() + self.start=self.count + for it in range(4,11): + label=QtGui.QLabel(line[it]) + pulsegrid.addWidget(label,self.row,0) + self.entry_var[self.count]=QtGui.QLineEdit() + self.entry_var[self.count].setMaximumWidth(150) + pulsegrid.addWidget(self.entry_var[self.count],self.row,1) + self.entry_var[self.count].setText("") + + try: + for child in root: + templist1=line[1] + templist2=templist1.split(' ') + if child.tag==templist2[0] and child.text==line[2]: + self.entry_var[self.count].setText(child[it-4].text) + except: + pass + + + self.row=self.row+1 + self.count=self.count+1 + self.end=self.count-1 + pulsebox.setLayout(pulsegrid) + + #CSS + pulsebox.setStyleSheet(" \ + QGroupBox { border: 1px solid gray; border-radius: 9px; margin-top: 0.5em; } \ + QGroupBox::title { subcontrol-origin: margin; left: 10px; padding: 0 3px 0 3px; } \ + ") + + self.grid.addWidget(pulsebox) + sourcelisttrack.append([track_id,'pulse',self.start,self.end]) + + elif line[2]=='pwl': + pwlbox=QtGui.QGroupBox() + pwlbox.setTitle(line[3]) + self.start=self.count + pwlgrid=QtGui.QGridLayout() + self.start=self.count + label=QtGui.QLabel(line[4]) + pwlgrid.addWidget(label,self.row,0) + self.entry_var[self.count]=QtGui.QLineEdit() + self.entry_var[self.count].setMaximumWidth(150) + pwlgrid.addWidget(self.entry_var[self.count],self.row,1) + self.entry_var[self.count].setText("") + + try: + for child in root: + templist1=line[1] + templist2=templist1.split(' ') + if child.tag==templist2[0] and child.text==line[2]: + self.entry_var[self.count].setText(child[0].text) + except: + pass + + + self.row=self.row+1 + self.end=self.count + self.count=self.count+1 + pwlbox.setLayout(pwlgrid) + + #CSS + pwlbox.setStyleSheet(" \ + QGroupBox { border: 1px solid gray; border-radius: 9px; margin-top: 0.5em; } \ + QGroupBox::title { subcontrol-origin: margin; left: 10px; padding: 0 3px 0 3px; } \ + ") + + self.grid.addWidget(pwlbox) + sourcelisttrack.append([track_id,'pwl',self.start,self.end]) + + elif line[2]=='exp': + expbox=QtGui.QGroupBox() + expbox.setTitle(line[3]) + expgrid=QtGui.QGridLayout() + self.start=self.count + for it in range(4,10): + label=QtGui.QLabel(line[it]) + expgrid.addWidget(label,self.row,0) + self.entry_var[self.count]=QtGui.QLineEdit() + self.entry_var[self.count].setMaximumWidth(150) + expgrid.addWidget(self.entry_var[self.count],self.row,1) + self.entry_var[self.count].setText("") + + try: + for child in root: + templist1=line[1] + templist2=templist1.split(' ') + if child.tag==templist2[0] and child.text==line[2]: + self.entry_var[self.count].setText(child[it-4].text) + except: + pass + + + self.row=self.row+1 + self.count=self.count+1 + self.end=self.count-1 + expbox.setLayout(expgrid) + + #CSS + expbox.setStyleSheet(" \ + QGroupBox { border: 1px solid gray; border-radius: 9px; margin-top: 0.5em; } \ + QGroupBox::title { subcontrol-origin: margin; left: 10px; padding: 0 3px 0 3px; } \ + ") + + self.grid.addWidget(expbox) + sourcelisttrack.append([track_id,'exp',self.start,self.end]) + + + self.count=self.count+1 + xml_num=xml_num+1 + + + else: + print "No source is present in your circuit" + + + #This is used to keep the track of dynamically created widget + self.obj_track.sourcelisttrack["ITEMS"] = sourcelisttrack + self.obj_track.source_entry_var["ITEMS"] = self.entry_var + self.show() + + + + + + + diff --git a/src/kicadtoNgspice/Source.pyc b/src/kicadtoNgspice/Source.pyc Binary files differnew file mode 100644 index 00000000..fe03449f --- /dev/null +++ b/src/kicadtoNgspice/Source.pyc diff --git a/src/kicadtoNgspice/SubcircuitTab.py b/src/kicadtoNgspice/SubcircuitTab.py new file mode 100644 index 00000000..e7a9ed66 --- /dev/null +++ b/src/kicadtoNgspice/SubcircuitTab.py @@ -0,0 +1,170 @@ +from PyQt4 import QtGui + +import TrackWidget +from projManagement import Validation +import os +from xml.etree import ElementTree as ET + +class SubcircuitTab(QtGui.QWidget): + """ + This class creates Subcircuit Tab in KicadtoNgspice Window + It dynamically creates the widget for subcircuits. + """ + + def __init__(self,schematicInfo,clarg1): + kicadFile = clarg1 + (projpath,filename)=os.path.split(kicadFile) + project_name=os.path.basename(projpath) + check=1 + try: + f=open(os.path.join(projpath,project_name+"_Previous_Values.xml"),'r') + tree=ET.parse(f) + parent_root=tree.getroot() + for child in parent_root: + if child.tag=="subcircuit": + root=child + except: + check=0 + print "Subcircuit Previous values XML is Empty" + + QtGui.QWidget.__init__(self) + + #Creating track widget object + self.obj_trac = TrackWidget.TrackWidget() + + #Creating validation object + self.obj_validation = Validation.Validation() + #Row and column count + self.row = 0 + self.count = 1 #Entry count + self.entry_var = {} + self.subcircuit_dict_beg={} + self.subcircuit_dict_end={} + #List to hold information about subcircuit + self.subDetail = {} + + #Stores the number of ports in each subcircuit + self.numPorts = [] + + #Set Layout + self.grid = QtGui.QGridLayout() + self.setLayout(self.grid) + + for eachline in schematicInfo: + words = eachline.split() + if eachline[0] == 'x': + print "Subcircuit : Words",words[0] + self.obj_trac.subcircuitList[project_name+words[0]]=words + self.subcircuit_dict_beg[words[0]]=self.count + subbox=QtGui.QGroupBox() + subgrid=QtGui.QGridLayout() + subbox.setTitle("Add subcircuit for "+words[len(words)-1]) + self.entry_var[self.count] = QtGui.QLineEdit() + self.entry_var[self.count].setText("") + + global path_name + try: + for child in root: + if child.tag[0]==eachline[0] and child.tag[1]==eachline[1]: + print "Subcircuit MATCHING---",child.tag[0],child.tag[1],eachline[0],eachline[1] + try: + if os.path.exists(child[0].text): + self.entry_var[self.count].setText(child[0].text) + path_name=child[0].text + else: + self.entry_var[self.count].setText("") + except: + print "Error when set text of subcircuit" + except: + print "Error before subcircuit" + + + subgrid.addWidget(self.entry_var[self.count],self.row,1) + self.addbtn = QtGui.QPushButton("Add") + self.addbtn.setObjectName("%d" %self.count) + #Send the number of ports specified with the given subcircuit for verification. + #eg. If the line is 'x1 4 0 3 ua741', there are 3 ports(4, 0 and 3). + self.numPorts.append(len(words)-2) + print "Number of ports of sub circuit : ",self.numPorts + self.addbtn.clicked.connect(self.trackSubcircuit) + subgrid.addWidget(self.addbtn,self.row,2) + subbox.setLayout(subgrid) + + #CSS + subbox.setStyleSheet(" \ + QGroupBox { border: 1px solid gray; border-radius: 9px; margin-top: 0.5em; } \ + QGroupBox::title { subcontrol-origin: margin; left: 10px; padding: 0 3px 0 3px; } \ + ") + + self.grid.addWidget(subbox) + + #Adding Subcircuit Details + self.subDetail[self.count] = words[0] + + #Increment row and widget count + + if self.entry_var[self.count].text()=="": + pass + else: + self.trackSubcircuitWithoutButton(self.count,path_name) + + self.subcircuit_dict_end[words[0]]=self.count + self.row = self.row+1 + self.count = self.count+1 + + self.show() + + + def trackSubcircuit(self): + """ + This function is use to keep track of all Subcircuit widget + """ + sending_btn = self.sender() + #print "Object Called is ",sending_btn.objectName() + self.widgetObjCount = int(sending_btn.objectName()) + + self.subfile = str(QtGui.QFileDialog.getExistingDirectory(self,"Open Subcircuit","../SubcircuitLibrary")) + self.reply = self.obj_validation.validateSub(self.subfile,self.numPorts[self.widgetObjCount - 1]) + if self.reply == "True": + #Setting Library to Text Edit Line + self.entry_var[self.widgetObjCount].setText(self.subfile) + self.subName = self.subDetail[self.widgetObjCount] + + #Storing to track it during conversion + + self.obj_trac.subcircuitTrack[self.subName] = self.subfile + elif self.reply == "PORT": + self.msg = QtGui.QErrorMessage(self) + self.msg.showMessage("Please select a Subcircuit with correct number of ports.") + self.msg.setWindowTitle("Error Message") + self.msg.show() + elif self.reply == "DIREC": + self.msg = QtGui.QErrorMessage(self) + self.msg.showMessage("Please select a valid Subcircuit directory (Containing '.sub' file).") + self.msg.setWindowTitle("Error Message") + self.msg.show() + + def trackSubcircuitWithoutButton(self,iter_value,path_value): + + self.widgetObjCount = iter_value + + self.subfile = path_value + self.reply = self.obj_validation.validateSub(self.subfile,self.numPorts[self.widgetObjCount - 1]) + if self.reply == "True": + #Setting Library to Text Edit Line + self.entry_var[self.widgetObjCount].setText(self.subfile) + self.subName = self.subDetail[self.widgetObjCount] + + #Storing to track it during conversion + + self.obj_trac.subcircuitTrack[self.subName] = self.subfile + elif self.reply == "PORT": + self.msg = QtGui.QErrorMessage(self) + self.msg.showMessage("Please select a Subcircuit with correct number of ports.") + self.msg.setWindowTitle("Error Message") + self.msg.show() + elif self.reply == "DIREC": + self.msg = QtGui.QErrorMessage(self) + self.msg.showMessage("Please select a valid Subcircuit directory (Containing '.sub' file).") + self.msg.setWindowTitle("Error Message") + self.msg.show()
\ No newline at end of file diff --git a/src/kicadtoNgspice/SubcircuitTab.pyc b/src/kicadtoNgspice/SubcircuitTab.pyc Binary files differnew file mode 100644 index 00000000..23f27032 --- /dev/null +++ b/src/kicadtoNgspice/SubcircuitTab.pyc diff --git a/src/kicadtoNgspice/TrackWidget.py b/src/kicadtoNgspice/TrackWidget.py new file mode 100644 index 00000000..56e84ce3 --- /dev/null +++ b/src/kicadtoNgspice/TrackWidget.py @@ -0,0 +1,29 @@ +class TrackWidget: + """ + This Class track the dynamically created widget of KicadtoNgSpice Window. + """ + #Track widget list for Source details + sourcelisttrack = {"ITEMS":"None"} + source_entry_var = {"ITEMS":"None"} + + #Track widget for analysis inserter details + AC_entry_var = {"ITEMS":"None"} + AC_Parameter = {"ITEMS":"None"} + DC_entry_var = {"ITEMS":"None"} + DC_Parameter = {"ITEMS":"None"} + TRAN_entry_var = {"ITEMS":"None"} + TRAN_Parameter = {"ITEMS":"None"} + set_CheckBox = {"ITEMS":"None"} + AC_type = {"ITEMS":"None"} + op_check = [] + #Track widget for Model detail + modelTrack = [] + model_entry_var = {} + + #Track Widget for Device Model detail + deviceModelTrack = {} + + #Track Widget for Subcircuits where directory has been selected + subcircuitTrack = {} + #Track subcircuits which are specified in .cir file + subcircuitList = {}
\ No newline at end of file diff --git a/src/kicadtoNgspice/TrackWidget.pyc b/src/kicadtoNgspice/TrackWidget.pyc Binary files differnew file mode 100644 index 00000000..40e0d68a --- /dev/null +++ b/src/kicadtoNgspice/TrackWidget.pyc diff --git a/src/kicadtoNgspice/__init__.py b/src/kicadtoNgspice/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/src/kicadtoNgspice/__init__.py diff --git a/src/kicadtoNgspice/__init__.pyc b/src/kicadtoNgspice/__init__.pyc Binary files differnew file mode 100644 index 00000000..a4a908e0 --- /dev/null +++ b/src/kicadtoNgspice/__init__.pyc |