import pySpice.global_data
from pySpice.element_class import *
from pySpice.parser.utils import *
import re
import math
import pdb
[docs]def parse_element(raw_line, node_dim, branch_dim):
'''
Parse a Circuit Element
:param raw_line: a string represent a element describe in Netlist
:param node_dim: The upper layer of this function retains a state counting how many node this circuit have. This value is passed into this function and here it decide whether to modify it or not basing on if encounter new nodes
:param branch_dim: similar to node_dim, the variabel counting how many linkages should appear in the matrix
:return:
+ node_dim
+ branch_dim
'''
line = raw_line.strip().lower().split()
if line[0][0] == 'r':
value = 1./extract(line[3])
ext_p = line[1]
ext_n = line[2]
loc_p, node_dim = address_transform(ext_p, node_dim)
loc_n, node_dim = address_transform(ext_n, node_dim)
name = line[0]
catagory = 'r'
temp = ele_2port(catagory,name,loc_p,loc_n,value)
pySpice.global_data.ELEMENT_DICT[name] = temp
elif line[0][0] == 'e':
name = line[0]
ext_p = line[1]
ext_n = line[2]
ext_ctrl_p = line[3]
ext_ctrl_n = line[4]
value = extract(line[5])
loc_p, node_dim = address_transform(ext_p, node_dim)
loc_n, node_dim = address_transform(ext_n, node_dim)
loc_ctrl_p, node_dim = address_transform(ext_ctrl_p, node_dim)
loc_ctrl_n, node_dim = address_transform(ext_ctrl_n, node_dim)
brch_num, branch_dim = address_transform(name, branch_dim)
temp = vcvs(loc_ctrl_p, loc_ctrl_n, brch_num, 'e', name, loc_p, loc_n, value)
pySpice.global_data.ELEMENT_DICT[name] = temp
elif line[0][0] == 'f':
name = line[0]
ext_p = line[1]
ext_n = line[2]
ext_ctrl_name = line[3]
value = extract(line[4])
loc_p, node_dim = address_transform(ext_p, node_dim)
loc_n, node_dim = address_transform(ext_n, node_dim)
loc_ctrl_brch, branch_dim = address_transform(ext_ctrl_name, branch_dim)
temp = cccs(loc_ctrl_brch, 'f', name, loc_p, loc_n, value)
pySpice.global_data.ELEMENT_DICT[name] = temp
elif line[0][0] == 'g':
name = line[0]
ext_p = line[1]
ext_n = line[2]
ext_ctrl_p = line[3]
ext_ctrl_n = line[4]
value = extract(line[5])
loc_p, node_dim = address_transform(ext_p, node_dim)
loc_n, node_dim = address_transform(ext_n, node_dim)
loc_ctrl_p, node_dim = address_transform(ext_ctrl_p, node_dim)
loc_ctrl_n, node_dim = address_transform(ext_ctrl_n, node_dim)
temp = vccs(loc_ctrl_p, loc_ctrl_n, 'g', name, loc_p, loc_n, value)
pySpice.global_data.ELEMENT_DICT[name] = temp
elif line[0][0] == 'h':
name = line[0]
loc_p, node_dim = address_transform(line[1], node_dim)
loc_n, node_dim = address_transform(line[2], node_dim)
loc_ctrl_brch, branch_dim = address_transform(line[3], branch_dim)
value = extract(line[4])
loc_brch, branch_dim = address_transform(name, branch_dim)
temp = ccvs(loc_brch, loc_ctrl_brch, 'g', name, loc_p, loc_n, value)
pySpice.global_data.ELEMENT_DICT[name] = temp
elif line[0][0] == 'c' or line[0][0] == 'l':
name = line[0]
loc_p, node_dim = address_transform(line[1], node_dim)
loc_n, node_dim = address_transform(line[2], node_dim)
value = extract(line[3])
if name[0] == 'c':
temp = capacitor('c', name, loc_p, loc_n, value)
else:
loc_brch, branch_dim = address_transform(name, branch_dim)
temp = inductor(loc_brch, 'l', name, loc_p, loc_n, value)
if (len(line) == 5 and line[4][1:3] == 'ic'):
temp.ic = (line[4].split('='))[1][:-1]
#current only support format like: IC=3v
pySpice.global_data.ELEMENT_DICT[name] = temp
elif line[0][0] == 'd':
name = line[0]
loc_p, node_dim = address_transform(line[1], node_dim)
loc_n, node_dim = address_transform(line[2], node_dim)
model = line[3]
temp = diode(model, 'd', name, loc_p, loc_n, 0)
m = re.search("ic=[0-9]*\?.[0-9]*[numkxg]?", raw_line.lower())
if m != None:
ic = extract(m.group().split('=')[1])
temp.ic = ic
pySpice.global_data.ELEMENT_DICT[name] = temp
elif line[0][0] == 'm':
#current only support w/l parmeter
name = line[0]
loc_d, node_dim = address_transform(line[1], node_dim)
loc_g, node_dim = address_transform(line[2], node_dim)
loc_s, node_dim = address_transform(line[3], node_dim)
loc_b, node_dim = address_transform(line[4], node_dim)
model = line[5]
temp = mos(name, model, loc_d, loc_g, loc_s, loc_b)
m = re.search("l=[0-9]*\.?[0-9]*[numkxg]?",raw_line.lower())
if m != None:
temp.l = extract(m.group().split('=')[1])
m = re.search("w=[0-9]*\.?[0-9]*[numkxg]?",raw_line.lower())
if m != None:
temp.w = extract(m.group().split('=')[1])
pySpice.global_data.ELEMENT_DICT[name] = temp
elif (line[0][0] == 'v' or line[0][0] == 'i'):
name = line[0]
loc_p, node_dim = address_transform(line[1], node_dim)
loc_n, node_dim = address_transform(line[2], node_dim)
if name[0] == 'v':
loc_brch, branch_dim = address_transform(name, branch_dim)
temp = v_src(loc_brch, 'v', name, loc_p, loc_n, 0)
else:
temp = i_src('i', name, loc_p, loc_n, 0)
if len(line) > 3:
if line[3] == 'dc':
temp.value = extract(line[4])
else:
m = re.match("-?[0-9]*\.?[0-9]*[numkxgNUMKXG]?",line[3])
if m!= None:
temp.value = extract(line[3])
m = re.search("ac\s+[0-9]+\.?[0-9]*[numkxg]?\s+[0-9]*\.?[0-9]*", raw_line.lower())
if m != None:
buf = m.group().split()
num = len(buf)
ac_mag = extract(buf[1])
ac_phase = 0
if num == 3:
ac_phase = eval(buf[2])
real = ac_mag * math.cos(math.pi * ac_phase/180)
imag = ac_mag * math.sin(math.pi * ac_phase/180)
temp.ac = complex(real, imag)
m = re.search("sin|exp|pulse|stair",raw_line.lower())
if m != None:
buf = raw_line.lower()[m.span()[0]:] #assume this part must appear last
tf = parse_timefunc(buf)
temp.tran = tf
pySpice.global_data.ELEMENT_DICT[name] = temp
return node_dim, branch_dim
[docs]def parse_timefunc(string):
"""
Parsing time-varient source into internal representation
In transient analysis, stimulates may take the form like PULSE, SIN, etc.This sub-utility to *parseline* function extract these part into designed data structures.
:param string: a slice of the element string like: "SIN(-1 1 1M)"
:return: a instance of the respctive data structure.
"""
if re.match('pulse',string) != None:
string = string[5:]
temp = string.find('(')
if temp != -1:
string = string[temp+1:]
temp = string.find(')')
string = string[:temp]
buf = string.split()
#here the time has a unit 's'
item = pulse_src(extract(buf[0]),extract(buf[1]), extract(buf[2][:-1]), extract(buf[3][:-1]), extract(buf[4][:-1]),extract(buf[5][:-1]), extract(buf[6][:-1]))
return item
elif re.match('sin',string) != None:
string = string[3:]
temp = string.find('(')
if temp != -1:
string = string[temp+1:]
temp = string.find(')')
string = string[:temp]
buf = string.split()
item = sin_src(extract(buf[0]), extract(buf[1]), extract(buf[2]))
return item
elif re.match('exp',string) != None:
print "exp haven't support"
return -1
elif re.match('stair', string) != None:
string = string[5:]
temp = string.find('(')
if temp != -1:
string = string[temp+1:]
temp = string.find(')')
string = string[:temp]
buf = string.split()
item = stair_src(extract(buf[0]), extract(buf[1]), extract(buf[2][:-1]))
return item
else:
print "Unrecognied Time-Function Indep. Source"
print "error raised, exiting now"
return -1
[docs]def parse_ctrl(raw_line):
"""
Parsing Control Command in SPICE
:param raw_line: a string represent a control command (start with a dot) describe in Netlist
:return:
Modify the *SETTING_LIST*, *ANALYSIS_LSIT*, *PRINT_DICT* in global_data
"""
line = raw_line.strip().lower().split()
if line[0][1:] == 'options':
pass
elif line[0][1:] == 'nodeset':
pass
elif line[0][1:] == 'ic':
pass
elif line[0][1:] == 'op':
pySpice.global_data.ANALYSIS_LIST.append(1)
elif line[0][1:] == 'dc':
start_l = extract(line[2])
stop_l = extract(line[3])
step_l = extract(line[4])
temp_gen = linear_generator(start_l, stop_l, step_l)
temp = analysis_dc(line[1], temp_gen)
if len(line) > 5:
temp.double_scan_flag = 1
temp.generator2 = linear_generator(extract(line[6]), extract(line[7]), extract(line[8]))
temp.swp_src2 = line[5]
pySpice.global_data.ANALYSIS_LIST.append(temp)
elif line[0][1:] == 'ac':
if line[1] == 'lin':
start_l = extract(line[3])
stop_l = extract(line[4])
step_l = (stop_l - start_l)/extract(line[2])
temp_gen = linear_generator(start_l, stop_l, step_l)
elif line[1] == 'oct':
start_l = extract(line[3])
stop_l = extract(line[4])
step_l = extract(line[2])
temp_gen = oct_generator(start_l, stop_l, step_l)
elif line[1] == 'dec':
start_l = extract(line[3])
stop_l = extract(line[4])
step_l = extract(line[2])
temp_gen = dec_generator(start_l, stop_l, step_l)
temp = analysis_ac(temp_gen)
pySpice.global_data.ANALYSIS_LIST.append(temp)
elif line[0][1:] == 'tran':
start_l = 0
stop_l = extract(line[2][:-1])
step_l = extract(line[1][:-1])
temp = analysis_tran(linear_generator(0, stop_l, step_l), step_l)
if(re.search('uic', raw_line.lower()) != None):
temp.uic_flag = 1;
if len(line) > 3:
if line[3] != 'uic':
temp.show_start = extract(line[3][:-1])
if len(line) > 4 and line[4] != 'uic':
temp.max_step = extract(line[4][:-1])
pySpice.global_data.ANALYSIS_LIST.append(temp)
elif (line[0][1:] == 'print') or (line[0][1:] == 'plot'):
for item in line[2:]:
temp = print_item(item)
if item[0] == 'v':
if line[1] == 'ac':
item = item[2:]
temp.ac_flag = item[1]
item = item.split('(')[1].split(')')[0]
if item.find(',') != -1:
temp.op_list.append(item.split(',')[0].strip())
temp.op_list.append(item.split(',')[1].strip())
temp.op_flag = 1
else:
temp.op_list.append(item[0].strip())
elif item[0] == 'i':
if line[1] == 'ac':
item = item[2:].strip('()')
item.ac_flag = item[1]
else:
item = item[1:].strip('()')
if item[0] != 'v':
print "Current not support print device current except current source"
print " Raise error"
return -1
else:
temp.op_list.append(item.strip())
temp.op_flag = 0
if line[1] == 'dc':
pySpice.global_data.PRINT_DICT['dc'].append(temp)
elif line[1] == 'tran':
pySpice.global_data.PRINT_DICT['tran'].append(temp)
elif line[1] == 'ac':
pySpice.global_data.PRINT_DICT['ac'].append(temp)
else:
print 'error'