我很难理解允许在参数名中使用“\”的语法(例如.net\<;8>;)。但是,“\”也用作续行(参见示例2)。Ex1工作正常,但是linebreak和identifier变量之间存在冲突
subckt INVERTER A Z gnd gnds vdd vdds
M1 (Z A vdd vdds) pmos w=0.4 l=0.1
M2 (Z A gnd gnds) nmos w=0.2 l=0.1
ends INVERTER
I1 (net1 net2 0 gnds! vdd! vdds!) INVERTER
subckt INVERTER_2 A Z gnd gnds vdd vdds
M1 (Z A vdd vdds) pmos w=0.4 l=0.1
M2 (Z A gnd gnds) nmos w=0.2 l=0.1
ends INVERTER_2
I2 (net\<8\> net2 0 gnds! vdd! vdds!) INVERTER_2
I3 (net1 net2 0 gnds! vdd! vdds!) INVERTER_2
subckt INVERTER A Z gnd gnds vdd vdds
M1 (Z A vdd vdds) pmos w=0.4 l=0.1
M2 (Z A gnd gnds) nmos w=0.2 l=0.1
ends INVERTER
I1 (net1 net2 0 gnds! vdd! vdds!) INVERTER
subckt INVERTER_2 A Z gnd gnds \
vdd vdds
M1 (Z A vdd vdds) pmos w=0.4 l=0.1
M2 (Z A gnd gnds) nmos w=0.2 l=0.1
ends INVERTER_2
I2 (net\<8\> net2 0 gnds! vdd! vdds!) INVERTER_2
I3 (net1 net2 0 gnds! vdd! vdds!) INVERTER_2
import pyparsing as pp
import json
EOL = pp.LineEnd().suppress() # end of line
linebreak = pp.Suppress(pp.Keyword('\\') + pp.LineEnd())
identifier = pp.Word(pp.alphanums + '_!<>\\')
number = pp.pyparsing_common.number
net = identifier
instref = identifier
instname = identifier
subcktname = identifier
subcktname_end = pp.Keyword("ends").suppress()
comment = pp.Suppress("//" + pp.SkipTo(pp.LineEnd()))
expression = pp.Word(pp.alphanums + '._*+-/()')
input_file = open(netlist.sp,'r')
file_string = input_file.read()
input_file.close()
for t, s, e in parse_netlist().scanString(file_string):
print(json.dumps(t.asDict()['netlist'], indent=2))
def parse_netlist():
pp.ParserElement.setDefaultWhitespaceChars(' \t')
nets = (pp.Optional(pp.Suppress('('))
+ pp.OneOrMore(net('net') | linebreak)
+ pp.Optional(pp.Suppress(')'))
)
inst_param_value = expression('expression')
inst_parameter = pp.Dict(pp.Group(identifier('param_name')
+ pp.Suppress("=")
+ inst_param_value('param_value')
))
parameters = pp.Group(pp.OneOrMore(inst_parameter | linebreak)
).setResultsName('parameters')
instance = pp.Dict(pp.Group(instname('inst_name')
+ nets('nets')
+ instref('reference')
+ pp.Optional(parameters)
+ EOL
)).setResultsName('instance', listAllMatches=True)
subckt_core = pp.Group(pp.ZeroOrMore(instance | EOL | comment)
).setResultsName('subckt_core', listAllMatches=True)
subckt = pp.Group(pp.Keyword("subckt").suppress()
+ subcktname('subckt_name')
+ nets('nets')
+ EOL
+ subckt_core
+ subcktname_end
+ pp.matchPreviousExpr(subcktname).suppress()
+ EOL
).setResultsName('subcircuit', listAllMatches=True)
netlist = pp.OneOrMore(subckt
| instance
| comment('comment')
| EOL
).setResultsName('netlist') + pp.StringEnd()
return netlist
[
{
"subckt_name": "INVERTER",
"net": "vdds",
"nets": [
"A",
"Z",
"gnd",
"gnds",
"vdd",
"vdds"
],
"subckt_core": [
{
"instance": [
{
"M1": {
"inst_name": "M1",
"net": "vdds",
"nets": [
"Z",
"A",
"vdd",
"vdds"
],
"reference": "pmos",
"parameters": {
"w": "0.4",
"l": "0.1"
}
}
},
{
"M2": {
"inst_name": "M2",
"net": "gnds",
"nets": [
"Z",
"A",
"gnd",
"gnds"
],
"reference": "nmos",
"parameters": {
"w": "0.2",
"l": "0.1"
}
}
}
]
}
]
},
{
"I1": {
"inst_name": "I1",
"net": "vdds!",
"nets": [
"net1",
"net2",
"0",
"gnds!",
"vdd!",
"vdds!"
],
"reference": "INVERTER",
"parameters": []
}
},
{
"subckt_name": "INVERTER_2",
"net": "vdds",
"nets": [
"A",
"Z",
"gnd",
"gnds",
"vdd",
"vdds"
],
"subckt_core": [
{
"instance": [
{
"M1": {
"inst_name": "M1",
"net": "vdds",
"nets": [
"Z",
"A",
"vdd",
"vdds"
],
"reference": "pmos",
"parameters": {
"w": "0.4",
"l": "0.1"
}
}
},
{
"M2": {
"inst_name": "M2",
"net": "gnds",
"nets": [
"Z",
"A",
"gnd",
"gnds"
],
"reference": "nmos",
"parameters": {
"w": "0.2",
"l": "0.1"
}
}
}
]
}
]
},
{
"I2": {
"inst_name": "I2",
"net": "vdds!",
"nets": [
"net\\<8\\>",
"net2",
"0",
"gnds!",
"vdd!",
"vdds!"
],
"reference": "INVERTER_2",
"parameters": []
}
},
{
"I3": {
"inst_name": "I3",
"net": "vdds!",
"nets": [
"net1",
"net2",
"0",
"gnds!",
"vdd!",
"vdds!"
],
"reference": "INVERTER_2",
"parameters": []
}
}
]
[
{
"I2": {
"inst_name": "I2",
"net": "vdds!",
"nets": [
"INST_IN\\<8\\>",
"net2",
"0",
"gnds!",
"vdd!",
"vdds!"
],
"reference": "INVERTER2",
"parameters": []
}
},
{
"I3": {
"inst_name": "I3",
"net": "vdds!",
"nets": [
"net1",
"net2",
"0",
"gnds!",
"vdd!",
"vdds!"
],
"reference": "INVERTER3",
"parameters": []
}
}
]
格式化子电路定义:
subckt SubcircuitName [(] node1 ... nodeN [)]
[ parameters name1=value1 ... [nameN=valueN]]
.
.
.
instance, model, ic, or nodeset statements—or
further subcircuit definitions
.
.
.
ends [SubcircuitName]
格式化实例语句:
name [(]node1 ... nodeN[)] master [[param1=value1] ...[paramN=valueN]]
Word
是pyparsing中最贪婪和最具攻击性的重复类型之一。所以你的两个表情:会有冲突。一旦标识符开始扫描匹配的字符,它就不会向前看下一个表达式是否应该停止
为了区分标识符中的“\”和作为延续符的“\”之间的区别,可以从
linebreak
开始。接下来,我们需要从标识符字中的字符中删除“\”:要在标识符中添加回“\”,我们需要更具体一些。不仅仅是任何“\”都可以,我们只需要不是换行符的“\”(也就是说,那些不在行尾的换行符)。我们可以用消极的态度来做。在接受反斜杠之前,首先确保它不是换行反斜杠:
现在identifier将是一个或多个单词项的集合,可以是上面定义的identifier单词,也可以是不是换行符的反斜杠
这让我们很接近,但如果您使用此标识符来解析“net\<;8>;“,您将得到:
如果在pyparsing
Combine
中包装标识符,那么所有这些都应该可以正常工作:提供:
编辑: 总而言之,以下是进行此更改所需的mod:
编辑2: 在方法
parse_netlist
中声明的这些行需要在导入pyparsing之后位于模块的顶部。否则,像linebreak这样的所有表达式都将使用默认的空白字符,包括\n
如果没有它们,
nets
的表达式将读取超过您的subckt
的第一行中的行尾,并将“M2:作为另一个网而不是作为subckt_core
中第一个instance
的标识符不知道为什么你的语法分析器会这样分解,最好把所有的位放在一起
相关问题 更多 >
编程相关推荐