条件SkipTo+可选匹配
Conditional SkipTo+Optional match
我正在尝试使用 pyparsing 解析一些 .LIB 文件。我有一个场景,我有一些遵循类似布局的字符串结构,但是内部有一些变体可以改变所需的语法。
TL;问题的 DR:
我需要能够将字符串的一部分绕过到下一个可能不存在的标记。
这是 LIB 文件的片段。
PIN EXAMPLE WITH NO TIMING
pin (core_c_sysclk ) {
clock : true ;
direction : input ;
capacitance : 0.0040;
max_transition : 0.1000;
related_ground_pin : "vss" ;
related_power_pin : "vcc" ;
fanout_load : 1.0000;
min_pulse_width_low : 0.1853;
min_pulse_width_high : 0.1249;
} /* End of pin core_c_sysclk */
bus (core_tx_td ){
bus_type : bus2 ;
/* Start of pin core_tx_td[9] */
PIN EXAMPLE WITH TIMING
pin (core_tx_td[9] ) {
direction : output ;
capacitance : 0.0005;
max_transition : 0.1000;
related_ground_pin : "vss" ;
related_power_pin : "vcc" ;
max_fanout : 15.0000;
max_capacitance : 0.1000;
/* Start of rising_edge arc of pin core_tx_td[9] wrt pin core_tx_tclk */
timing() { <----WHAT I WANT (to know if this is in the pin)
timing_type : rising_edge ;
timing_sense : non_unate ;
min_delay_arc : "true" ;
related_pin :" core_tx_tclk "; <----WHAT I WANT (core_tx_tclk in this case)
rise_transition (lut_timing_4 ){
values(\
REMOVED FOR CLARITY
);
}
fall_transition (lut_timing_4 ){
values(\
REMOVED FOR CLARITY
);
}
cell_rise (lut_timing_4 ){
values(\
REMOVED FOR CLARITY
);
}
cell_fall (lut_timing_4 ){
values(\
REMOVED FOR CLARITY
);
}
} /* End of rising_edge arc of pin core_tx_td[9] wrt pin core_tx_tclk */
.....More but not really needed for example
感兴趣的主要值是 'pin' 名称、时钟类型、方向,如果 timing() 存在,相关的引脚。
到目前为止,这是我解析字符串的内容:
LP = '('
RP = ')'
LCB = '{'
RCB = '}'
COM = ','
#Pins/Signals
pin_dec = (Keyword('pin') + LP + Word(alphanums+'_/[]').setResultsName('name') + RP).setResultsName('pin_dec')
pin_clk = (Keyword('clock') + ':' + Word(alphanums+'_/').setResultsName('is_clk') + ';').setResultsName('pin_clk')
pin_dir = (Keyword('direction') + ':' + Word(alphanums+'_/').setResultsName('dir') + ';').setResultsName('pin_dir')
pin_arc = (Keyword('related_pin') + ':' + '"' + Word(alphanums+'_/[]').setResultsName('name') + '"' + ';').setResultsName('pin_arc')
pin_timing = (Keyword('timing') + LP + RP + LCB + SkipTo(pin_arc) + Optional(pin_arc)).setResultsName('pin_timing')
pin_end = Keyword('} /* End of pin') + SkipTo('*/')
pin = pin_dec + LCB + Optional(pin_clk) + Optional(pin_dir) + SkipTo(Optional(pin_timing)) + SkipTo(pin_end) + pin_end
pin ()、时钟检查和方向检查很简单并且似乎可以工作。我的问题是 pin_timing
和 pin_arc
检查。在某些情况下,如代码中所示,您可以有不需要的额外信息行。我尝试使用 SkipTo(pin_timing),但是 pin_timing 元素可能不存在,所以如果可能的话我想跳过它。
我尝试过 Optional(SkipTo(pin_timing))
和 SkipTo(Optional(pin_timing))
,但这些似乎都没有给我正确的结果。这是测试示例字符串的代码片段:
for bla in pin.searchString(test_str):
print('========')
print('Pin name: ' + bla.pin_dec.name)
if bla.pin_dir:
print('Pin Dir: ' + bla.pin_dir.dir)
if bla.pin_clk:
print('Pin Clk: ' + bla.pin_clk.is_clk)
#if bla.pin_timing: just trying to print for debug
print('Pin Timing: ' + bla.pin_timing)
输出如下:
========
Pin name: core_c_sysclk
Pin Dir: input
Pin Clk: true
Pin Timing:
========
Pin name: core_tx_pwr_st[2]
Pin Dir: output
Pin Timing:
========
Pin name: core_tx_pwr_st[1]
Pin Dir: output
Pin Timing:
========
Pin name: core_tx_pwr_st[0]
Pin Dir: output
Pin Timing:
========
Pin name: core_tx_td[9]
Pin Dir: output
Pin Timing:
在 pin_timing 上设置调试(使用 pin_timing.setDebug()
),我得到以下输出:
Match {"timing" "(" ")" "{" SkipTo:({"related_pin" ":" """ W:(abcd...) """ ";"}) [{"related_pin" ":" """ W:(abcd...) """ ";"}]} at loc 596(22,7)
Exception raised:Expected "timing" (at char 596), (line:22, col:7)
基于此,它在 max_transition
行引发异常。我一直无法理解为什么要这样做。还想知道为什么它不在 capacitance
行上给出相同的异常。我猜我使用 Optional
+ SkipTo
不正确,所以如果有任何示例可用于跳到可选令牌,如果不可用则绕过,那会很好看。我查看了 PyParsing 文档和几个 SO 主题,但是其中大多数似乎都没有回答这个特定问题。
我想知道是否需要从文件中获取整个 pin()
字符串,然后执行递归 parse/search 来提取 timing/related_pin,但是我想看看是否在尝试之前有一个更简单的解决方案。
谢谢
Optional
和 SkipTo
一起使用时通常需要小心。 SkipTo
通常会查找其目标表达式,而不考虑解析器中它之前或之后的其他表达式。
这是一个例子。使用 SkipTo
解析这些行:
a b c z
a d e 100 d z
以 'a' 开始,以 'z' 结束,中间有一些字母,可能还有一个整数。
我们可以这样写:
start = pp.Char('a').setName('start')
end = pp.Char('z').setName('end')
num = pp.Word(pp.nums).setName('num')
我们将使用 SkipTo
因为谁知道里面还有什么?
expr = (start
+ pp.Optional(pp.SkipTo(num) + num)
+ pp.SkipTo(end)
+ end)
对其进行一些测试:
expr.runTests("""
a b c z
a d e 100 d z
a 100 b d z
""")
而且他们看起来都很不错:
a b c z
['a', 'b c ', 'z']
a d e 100 d z
['a', 'd e ', '100', 'd ', 'z']
a 100 b d z
['a', '', '100', 'b d ', 'z']
但是如果可以有多个表达式,那么 SkipTo 可能会跳过太多:
pp.OneOrMore(pp.Group(expr)).runTests("""
a b c z
a d e 100 d z
a 100 b d z
# not what we want
a b c z a d e 100 d z
""")
给出:
a b c z
[['a', 'b c ', 'z']]
[0]:
['a', 'b c ', 'z']
a d e 100 d z
[['a', 'd e ', '100', 'd ', 'z']]
[0]:
['a', 'd e ', '100', 'd ', 'z']
a 100 b d z
[['a', '', '100', 'b d ', 'z']]
[0]:
['a', '', '100', 'b d ', 'z']
# not what we want
a b c z a d e 100 d z
[['a', 'b c z a d e ', '100', 'd ', 'z']]
[0]:
['a', 'b c z a d e ', '100', 'd ', 'z']
最后一个测试字符串显示 SkipTo
跳过第一组的末尾,直到它在第二组中达到“100”,我们只得到一个大组而不是两个。
我们需要向 SkipTo
表明它无法读取超过查找 num 的组的末尾。为此,请使用 failOn
:
expr = (start
+ pp.Optional(pp.SkipTo(num, failOn=end) + num)
+ pp.SkipTo(end)
+ end)
如果在找到 num
之前遇到 end
表达式,我们希望跳过失败。因为我们已经说过这是可选的,所以没问题,现在我们的测试看起来像:
pp.OneOrMore(pp.Group(expr)).runTests("""
# better
a b c z a d e 100 d z
""")
# better
a b c z a d e 100 d z
[['a', 'b c ', 'z'], ['a', 'd e ', '100', 'd ', 'z']]
[0]:
['a', 'b c ', 'z']
[1]:
['a', 'd e ', '100', 'd ', 'z']
现在看看你的例子,这是你的语法。我做了一些更改,主要是将 expr.setResultsName("some_name")
更改为 expr("some_name")
并 Group
编辑了你的表达式,以便你的分层命名有效,主要是机器人,在你的可选 [=22= 中添加 failOn
] 这样它就不会跳过 pin_end
表达式:
identifier = Word(alphanums+'_/[]')
pin_dec = Group(Keyword('pin') + LP + identifier('name') + RP)('pin_dec')
pin_clk = Group(Keyword('clock') + ':' + identifier('is_clk') + ';')('pin_clk')
pin_dir = Group(Keyword('direction') + ':' + identifier('dir') + ';')('pin_dir')
pin_arc = Group(Keyword('related_pin')
+ ':'
+ '"' + identifier('name') + '"'
+ ';')('pin_arc')
pin_timing = Group(Keyword('timing')
+ LP + RP
+ LCB
+ SkipTo(pin_arc)
+ Optional(pin_arc))('pin_timing')
pin_end = RCB + Optional(cStyleComment)
pin = Group(pin_dec
+ LCB
+ Optional(pin_clk)
+ Optional(pin_dir)
+ Optional(SkipTo(pin_timing, failOn=pin_end))
+ SkipTo(pin_end)
+ pin_end
for parsed in pin.searchString(sample):
print(parsed.dump())
print()
给予:
[[['pin', '(', 'core_c_sysclk', ')'], '{', ['clock', ':', 'true', ';'], ['direction', ':', 'input', ';'], 'capacitance : 0.0040;\n max_transition : 0.1000;\n related_ground_pin : "vss" ;\n related_power_pin : "vcc" ;\n fanout_load : 1.0000;\n min_pulse_width_low : 0.1853;\n min_pulse_width_high : 0.1249;', '', '}', '/* End of pin core_c_sysclk */']]
[0]:
[['pin', '(', 'core_c_sysclk', ')'], '{', ['clock', ':', 'true', ';'], ['direction', ':', 'input', ';'], 'capacitance : 0.0040;\n max_transition : 0.1000;\n related_ground_pin : "vss" ;\n related_power_pin : "vcc" ;\n fanout_load : 1.0000;\n min_pulse_width_low : 0.1853;\n min_pulse_width_high : 0.1249;', '', '}', '/* End of pin core_c_sysclk */']
- pin_clk: ['clock', ':', 'true', ';']
- is_clk: 'true'
- pin_dec: ['pin', '(', 'core_c_sysclk', ')']
- name: 'core_c_sysclk'
- pin_dir: ['direction', ':', 'input', ';']
- dir: 'input'
[[['pin', '(', 'core_tx_td[9]', ')'], '{', ['direction', ':', 'output', ';'], 'capacitance : 0.0005;\n max_transition : 0.1000;\n related_ground_pin : "vss" ;\n related_power_pin : "vcc" ;\n max_fanout : 15.0000;\n max_capacitance : 0.1000;\n\n /* Start of rising_edge arc of pin core_tx_td[9] wrt pin core_tx_tclk */\n ', 'timing() { <----WHAT I WANT (to know if this is in the pin)\n timing_type : rising_edge ;\n timing_sense : non_unate ;\n min_delay_arc : "true" ;\n related_pin :" core_tx_tclk "; <----WHAT I WANT (core_tx_tclk in this case)\n rise_transition (lut_timing_4 ){\n values( REMOVED FOR CLARITY\n );\n ', '}']]
[0]:
[['pin', '(', 'core_tx_td[9]', ')'], '{', ['direction', ':', 'output', ';'], 'capacitance : 0.0005;\n max_transition : 0.1000;\n related_ground_pin : "vss" ;\n related_power_pin : "vcc" ;\n max_fanout : 15.0000;\n max_capacitance : 0.1000;\n\n /* Start of rising_edge arc of pin core_tx_td[9] wrt pin core_tx_tclk */\n ', 'timing() { <----WHAT I WANT (to know if this is in the pin)\n timing_type : rising_edge ;\n timing_sense : non_unate ;\n min_delay_arc : "true" ;\n related_pin :" core_tx_tclk "; <----WHAT I WANT (core_tx_tclk in this case)\n rise_transition (lut_timing_4 ){\n values( REMOVED FOR CLARITY\n );\n ', '}']
- pin_dec: ['pin', '(', 'core_tx_td[9]', ')']
- name: 'core_tx_td[9]'
- pin_dir: ['direction', ':', 'output', ';']
- dir: 'output'
所以你真的很接近,只需要正确构建 Optional
和 SkipTo
,并添加 failOn
和一些 Group
。其余的几乎就是您的方式。
我正在尝试使用 pyparsing 解析一些 .LIB 文件。我有一个场景,我有一些遵循类似布局的字符串结构,但是内部有一些变体可以改变所需的语法。
TL;问题的 DR: 我需要能够将字符串的一部分绕过到下一个可能不存在的标记。
这是 LIB 文件的片段。
PIN EXAMPLE WITH NO TIMING
pin (core_c_sysclk ) {
clock : true ;
direction : input ;
capacitance : 0.0040;
max_transition : 0.1000;
related_ground_pin : "vss" ;
related_power_pin : "vcc" ;
fanout_load : 1.0000;
min_pulse_width_low : 0.1853;
min_pulse_width_high : 0.1249;
} /* End of pin core_c_sysclk */
bus (core_tx_td ){
bus_type : bus2 ;
/* Start of pin core_tx_td[9] */
PIN EXAMPLE WITH TIMING
pin (core_tx_td[9] ) {
direction : output ;
capacitance : 0.0005;
max_transition : 0.1000;
related_ground_pin : "vss" ;
related_power_pin : "vcc" ;
max_fanout : 15.0000;
max_capacitance : 0.1000;
/* Start of rising_edge arc of pin core_tx_td[9] wrt pin core_tx_tclk */
timing() { <----WHAT I WANT (to know if this is in the pin)
timing_type : rising_edge ;
timing_sense : non_unate ;
min_delay_arc : "true" ;
related_pin :" core_tx_tclk "; <----WHAT I WANT (core_tx_tclk in this case)
rise_transition (lut_timing_4 ){
values(\
REMOVED FOR CLARITY
);
}
fall_transition (lut_timing_4 ){
values(\
REMOVED FOR CLARITY
);
}
cell_rise (lut_timing_4 ){
values(\
REMOVED FOR CLARITY
);
}
cell_fall (lut_timing_4 ){
values(\
REMOVED FOR CLARITY
);
}
} /* End of rising_edge arc of pin core_tx_td[9] wrt pin core_tx_tclk */
.....More but not really needed for example
感兴趣的主要值是 'pin' 名称、时钟类型、方向,如果 timing() 存在,相关的引脚。
到目前为止,这是我解析字符串的内容:
LP = '('
RP = ')'
LCB = '{'
RCB = '}'
COM = ','
#Pins/Signals
pin_dec = (Keyword('pin') + LP + Word(alphanums+'_/[]').setResultsName('name') + RP).setResultsName('pin_dec')
pin_clk = (Keyword('clock') + ':' + Word(alphanums+'_/').setResultsName('is_clk') + ';').setResultsName('pin_clk')
pin_dir = (Keyword('direction') + ':' + Word(alphanums+'_/').setResultsName('dir') + ';').setResultsName('pin_dir')
pin_arc = (Keyword('related_pin') + ':' + '"' + Word(alphanums+'_/[]').setResultsName('name') + '"' + ';').setResultsName('pin_arc')
pin_timing = (Keyword('timing') + LP + RP + LCB + SkipTo(pin_arc) + Optional(pin_arc)).setResultsName('pin_timing')
pin_end = Keyword('} /* End of pin') + SkipTo('*/')
pin = pin_dec + LCB + Optional(pin_clk) + Optional(pin_dir) + SkipTo(Optional(pin_timing)) + SkipTo(pin_end) + pin_end
pin ()、时钟检查和方向检查很简单并且似乎可以工作。我的问题是 pin_timing
和 pin_arc
检查。在某些情况下,如代码中所示,您可以有不需要的额外信息行。我尝试使用 SkipTo(pin_timing),但是 pin_timing 元素可能不存在,所以如果可能的话我想跳过它。
我尝试过 Optional(SkipTo(pin_timing))
和 SkipTo(Optional(pin_timing))
,但这些似乎都没有给我正确的结果。这是测试示例字符串的代码片段:
for bla in pin.searchString(test_str):
print('========')
print('Pin name: ' + bla.pin_dec.name)
if bla.pin_dir:
print('Pin Dir: ' + bla.pin_dir.dir)
if bla.pin_clk:
print('Pin Clk: ' + bla.pin_clk.is_clk)
#if bla.pin_timing: just trying to print for debug
print('Pin Timing: ' + bla.pin_timing)
输出如下:
========
Pin name: core_c_sysclk
Pin Dir: input
Pin Clk: true
Pin Timing:
========
Pin name: core_tx_pwr_st[2]
Pin Dir: output
Pin Timing:
========
Pin name: core_tx_pwr_st[1]
Pin Dir: output
Pin Timing:
========
Pin name: core_tx_pwr_st[0]
Pin Dir: output
Pin Timing:
========
Pin name: core_tx_td[9]
Pin Dir: output
Pin Timing:
在 pin_timing 上设置调试(使用 pin_timing.setDebug()
),我得到以下输出:
Match {"timing" "(" ")" "{" SkipTo:({"related_pin" ":" """ W:(abcd...) """ ";"}) [{"related_pin" ":" """ W:(abcd...) """ ";"}]} at loc 596(22,7)
Exception raised:Expected "timing" (at char 596), (line:22, col:7)
基于此,它在 max_transition
行引发异常。我一直无法理解为什么要这样做。还想知道为什么它不在 capacitance
行上给出相同的异常。我猜我使用 Optional
+ SkipTo
不正确,所以如果有任何示例可用于跳到可选令牌,如果不可用则绕过,那会很好看。我查看了 PyParsing 文档和几个 SO 主题,但是其中大多数似乎都没有回答这个特定问题。
我想知道是否需要从文件中获取整个 pin()
字符串,然后执行递归 parse/search 来提取 timing/related_pin,但是我想看看是否在尝试之前有一个更简单的解决方案。
谢谢
Optional
和 SkipTo
一起使用时通常需要小心。 SkipTo
通常会查找其目标表达式,而不考虑解析器中它之前或之后的其他表达式。
这是一个例子。使用 SkipTo
解析这些行:
a b c z
a d e 100 d z
以 'a' 开始,以 'z' 结束,中间有一些字母,可能还有一个整数。
我们可以这样写:
start = pp.Char('a').setName('start')
end = pp.Char('z').setName('end')
num = pp.Word(pp.nums).setName('num')
我们将使用 SkipTo
因为谁知道里面还有什么?
expr = (start
+ pp.Optional(pp.SkipTo(num) + num)
+ pp.SkipTo(end)
+ end)
对其进行一些测试:
expr.runTests("""
a b c z
a d e 100 d z
a 100 b d z
""")
而且他们看起来都很不错:
a b c z
['a', 'b c ', 'z']
a d e 100 d z
['a', 'd e ', '100', 'd ', 'z']
a 100 b d z
['a', '', '100', 'b d ', 'z']
但是如果可以有多个表达式,那么 SkipTo 可能会跳过太多:
pp.OneOrMore(pp.Group(expr)).runTests("""
a b c z
a d e 100 d z
a 100 b d z
# not what we want
a b c z a d e 100 d z
""")
给出:
a b c z
[['a', 'b c ', 'z']]
[0]:
['a', 'b c ', 'z']
a d e 100 d z
[['a', 'd e ', '100', 'd ', 'z']]
[0]:
['a', 'd e ', '100', 'd ', 'z']
a 100 b d z
[['a', '', '100', 'b d ', 'z']]
[0]:
['a', '', '100', 'b d ', 'z']
# not what we want
a b c z a d e 100 d z
[['a', 'b c z a d e ', '100', 'd ', 'z']]
[0]:
['a', 'b c z a d e ', '100', 'd ', 'z']
最后一个测试字符串显示 SkipTo
跳过第一组的末尾,直到它在第二组中达到“100”,我们只得到一个大组而不是两个。
我们需要向 SkipTo
表明它无法读取超过查找 num 的组的末尾。为此,请使用 failOn
:
expr = (start
+ pp.Optional(pp.SkipTo(num, failOn=end) + num)
+ pp.SkipTo(end)
+ end)
如果在找到 num
之前遇到 end
表达式,我们希望跳过失败。因为我们已经说过这是可选的,所以没问题,现在我们的测试看起来像:
pp.OneOrMore(pp.Group(expr)).runTests("""
# better
a b c z a d e 100 d z
""")
# better
a b c z a d e 100 d z
[['a', 'b c ', 'z'], ['a', 'd e ', '100', 'd ', 'z']]
[0]:
['a', 'b c ', 'z']
[1]:
['a', 'd e ', '100', 'd ', 'z']
现在看看你的例子,这是你的语法。我做了一些更改,主要是将 expr.setResultsName("some_name")
更改为 expr("some_name")
并 Group
编辑了你的表达式,以便你的分层命名有效,主要是机器人,在你的可选 [=22= 中添加 failOn
] 这样它就不会跳过 pin_end
表达式:
identifier = Word(alphanums+'_/[]')
pin_dec = Group(Keyword('pin') + LP + identifier('name') + RP)('pin_dec')
pin_clk = Group(Keyword('clock') + ':' + identifier('is_clk') + ';')('pin_clk')
pin_dir = Group(Keyword('direction') + ':' + identifier('dir') + ';')('pin_dir')
pin_arc = Group(Keyword('related_pin')
+ ':'
+ '"' + identifier('name') + '"'
+ ';')('pin_arc')
pin_timing = Group(Keyword('timing')
+ LP + RP
+ LCB
+ SkipTo(pin_arc)
+ Optional(pin_arc))('pin_timing')
pin_end = RCB + Optional(cStyleComment)
pin = Group(pin_dec
+ LCB
+ Optional(pin_clk)
+ Optional(pin_dir)
+ Optional(SkipTo(pin_timing, failOn=pin_end))
+ SkipTo(pin_end)
+ pin_end
for parsed in pin.searchString(sample):
print(parsed.dump())
print()
给予:
[[['pin', '(', 'core_c_sysclk', ')'], '{', ['clock', ':', 'true', ';'], ['direction', ':', 'input', ';'], 'capacitance : 0.0040;\n max_transition : 0.1000;\n related_ground_pin : "vss" ;\n related_power_pin : "vcc" ;\n fanout_load : 1.0000;\n min_pulse_width_low : 0.1853;\n min_pulse_width_high : 0.1249;', '', '}', '/* End of pin core_c_sysclk */']]
[0]:
[['pin', '(', 'core_c_sysclk', ')'], '{', ['clock', ':', 'true', ';'], ['direction', ':', 'input', ';'], 'capacitance : 0.0040;\n max_transition : 0.1000;\n related_ground_pin : "vss" ;\n related_power_pin : "vcc" ;\n fanout_load : 1.0000;\n min_pulse_width_low : 0.1853;\n min_pulse_width_high : 0.1249;', '', '}', '/* End of pin core_c_sysclk */']
- pin_clk: ['clock', ':', 'true', ';']
- is_clk: 'true'
- pin_dec: ['pin', '(', 'core_c_sysclk', ')']
- name: 'core_c_sysclk'
- pin_dir: ['direction', ':', 'input', ';']
- dir: 'input'
[[['pin', '(', 'core_tx_td[9]', ')'], '{', ['direction', ':', 'output', ';'], 'capacitance : 0.0005;\n max_transition : 0.1000;\n related_ground_pin : "vss" ;\n related_power_pin : "vcc" ;\n max_fanout : 15.0000;\n max_capacitance : 0.1000;\n\n /* Start of rising_edge arc of pin core_tx_td[9] wrt pin core_tx_tclk */\n ', 'timing() { <----WHAT I WANT (to know if this is in the pin)\n timing_type : rising_edge ;\n timing_sense : non_unate ;\n min_delay_arc : "true" ;\n related_pin :" core_tx_tclk "; <----WHAT I WANT (core_tx_tclk in this case)\n rise_transition (lut_timing_4 ){\n values( REMOVED FOR CLARITY\n );\n ', '}']]
[0]:
[['pin', '(', 'core_tx_td[9]', ')'], '{', ['direction', ':', 'output', ';'], 'capacitance : 0.0005;\n max_transition : 0.1000;\n related_ground_pin : "vss" ;\n related_power_pin : "vcc" ;\n max_fanout : 15.0000;\n max_capacitance : 0.1000;\n\n /* Start of rising_edge arc of pin core_tx_td[9] wrt pin core_tx_tclk */\n ', 'timing() { <----WHAT I WANT (to know if this is in the pin)\n timing_type : rising_edge ;\n timing_sense : non_unate ;\n min_delay_arc : "true" ;\n related_pin :" core_tx_tclk "; <----WHAT I WANT (core_tx_tclk in this case)\n rise_transition (lut_timing_4 ){\n values( REMOVED FOR CLARITY\n );\n ', '}']
- pin_dec: ['pin', '(', 'core_tx_td[9]', ')']
- name: 'core_tx_td[9]'
- pin_dir: ['direction', ':', 'output', ';']
- dir: 'output'
所以你真的很接近,只需要正确构建 Optional
和 SkipTo
,并添加 failOn
和一些 Group
。其余的几乎就是您的方式。