Skip to content

Commit a90c1f4

Browse files
committed
Improve PART format parsing (ise, libero and openflow)
1 parent 25e683c commit a90c1f4

File tree

6 files changed

+147
-32
lines changed

6 files changed

+147
-32
lines changed

docs/tools.rst

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,13 @@ Example:
7070
7171
prj = Ise()
7272
73+
Valid PART formats:
74+
75+
.. code::
76+
77+
<DEVICE>-<SPEED>-<PACKAGE>
78+
<DEVICE>-<PACKAGE>-<SPEED>
79+
7380
Libero
7481
------
7582

@@ -87,6 +94,19 @@ Example:
8794
8895
prj = Libero()
8996
97+
Valid PART formats:
98+
99+
.. code::
100+
101+
<DEVICE>-<PACKAGE>
102+
<DEVICE>-<SPEED><PACKAGE>
103+
<DEVICE>-<SPEED>-<PACKAGE>
104+
<DEVICE>-<PACKAGE>-<SPEED>
105+
<DEVICE>-<PACKAGE><RANGE>
106+
<DEVICE>-<SPEED><PACKAGE><RANGE>
107+
<DEVICE>-<SPEED>-<PACKAGE><RANGE>
108+
<DEVICE>-<PACKAGE><RANGE>-<SPEED>
109+
90110
Openflow
91111
--------
92112

@@ -116,6 +136,12 @@ Example:
116136
117137
prj = Openflow()
118138
139+
Valid PART formats:
140+
141+
.. code::
142+
143+
<DEVICE>-<PACKAGE>
144+
119145
Quartus
120146
-------
121147

pyfpga/ise.py

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,9 @@ def get_info(part):
4343
"""Get info about the FPGA part.
4444
4545
:param part: the FPGA part as specified by the tool
46-
:returns: a dictionary with the keys family, device, speed and package
46+
:returns: a dict with the keys family, device, speed and package
4747
"""
48-
part = part.lower()
48+
part = part.lower().replace(' ', '')
4949
# Looking for the family
5050
family = None
5151
families = {
@@ -71,24 +71,26 @@ def get_info(part):
7171
if re.match(key, part):
7272
family = value
7373
break
74-
# Looking for the device, package and speed
74+
# Looking for the other values
7575
device = None
7676
speed = None
7777
package = None
7878
aux = part.split('-')
7979
if len(aux) == 3:
8080
device = aux[0]
8181
if len(aux[1]) < len(aux[2]):
82-
speed = aux[1]
82+
speed = f'-{aux[1]}'
8383
package = aux[2]
8484
else:
85-
speed = aux[2]
85+
speed = f'-{aux[2]}'
8686
package = aux[1]
8787
else:
88-
raise ValueError(
89-
'Part must be DEVICE-SPEED-PACKAGE or DEVICE-PACKAGE-SPEED'
90-
)
88+
valid = 'DEVICE-SPEED-PACKAGE or DEVICE-PACKAGE-SPEED'
89+
raise ValueError(f'Invalid PART format ({valid})')
9190
# Finish
9291
return {
93-
'family': family, 'device': device, 'speed': speed, 'package': package
92+
'family': family,
93+
'device': device,
94+
'speed': speed,
95+
'package': package
9496
}

pyfpga/libero.py

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515

1616
class Libero(Project):
17-
"""Class to support Libero."""
17+
"""Class to support Libero projects."""
1818

1919
def _configure(self):
2020
tool = 'libero'
@@ -45,12 +45,12 @@ def get_info(part):
4545
:param part: the FPGA part as specified by the tool
4646
:returns: a dict with the keys family, device, speed, package and prange
4747
"""
48-
part = part.lower()
48+
part = part.lower().replace(' ', '')
4949
# Looking for the family
5050
family = None
5151
families = {
5252
r'm2s': 'SmartFusion2',
53-
r'm2gl': 'Igloo2',
53+
r'm2gl': 'IGLOO2',
5454
r'rt4g': 'RTG4',
5555
r'mpfs': 'PolarFireSoC',
5656
r'mpf': 'PolarFire',
@@ -67,16 +67,20 @@ def get_info(part):
6767
if re.match(key, part):
6868
family = value
6969
break
70-
# Looking for the device, speed and package
70+
# Looking for the other values
7171
device = None
7272
speed = None
7373
package = None
7474
prange = None
7575
aux = part.split('-')
7676
if len(aux) == 2:
7777
device = aux[0]
78-
speed = 'STD'
7978
package = aux[1]
79+
if package[0].isdigit():
80+
speed = f'-{package[0]}'
81+
package = package[1:]
82+
else:
83+
speed = 'STD'
8084
elif len(aux) == 3:
8185
device = aux[0]
8286
if len(aux[1]) < len(aux[2]):
@@ -86,10 +90,8 @@ def get_info(part):
8690
speed = f'-{aux[2]}'
8791
package = aux[1]
8892
else:
89-
raise ValueError(
90-
'Part must be DEVICE-SPEED-PACKAGE or DEVICE-PACKAGE'
91-
)
92-
# Looking for a part_range
93+
valid = 'DEVICE-[SPEED][-]PACKAGE[PRANGE][-SPEED]'
94+
raise ValueError(f'Invalid PART format ({valid})')
9395
pranges = {
9496
'c': 'COM',
9597
'e': 'EXT',

pyfpga/openflow.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,9 @@ def get_info(part):
3434
"""Get info about the FPGA part.
3535
3636
:param part: the FPGA part as specified by the tool
37-
:returns: a dictionary with the keys family, device and package
37+
:returns: a dict with the keys family, device and package
3838
"""
39-
part = part.lower()
39+
part = part.lower().replace(' ', '')
4040
# Looking for the family
4141
family = None
4242
families = [
@@ -62,7 +62,7 @@ def get_info(part):
6262
]
6363
if part.startswith(tuple(families)):
6464
family = 'ecp5'
65-
# Looking for the device and package
65+
# Looking for the other values
6666
device = None
6767
package = None
6868
aux = part.split('-')
@@ -73,11 +73,16 @@ def get_info(part):
7373
device = f'{aux[0]}-{aux[1]}'
7474
package = aux[2]
7575
else:
76-
raise ValueError('Part must be DEVICE-PACKAGE')
76+
valid = 'DEVICE-PACKAGE'
77+
raise ValueError(f'Invalid PART format ({valid})')
7778
if family in ['lp4k', 'hx4k']: # See http://www.clifford.at/icestorm
7879
device = device.replace('4', '8')
7980
package += ":4k"
8081
if family == 'ecp5':
8182
package = package.upper()
8283
# Finish
83-
return {'family': family, 'device': device, 'package': package}
84+
return {
85+
'family': family,
86+
'device': device,
87+
'package': package
88+
}

pyfpga/templates/ise.jinja

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ project new {{ project }}.xise
1313
project set family {{ family }}
1414
project set device {{ device }}
1515
project set package {{ package }}
16-
project set speed -{{ speed }}
16+
project set speed {{ speed }}
1717

1818
{% if hooks %}{{ hooks.precfg | join('\n') }}{% endif %}
1919

tests/test_part.py

Lines changed: 88 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,25 +7,105 @@ def test_ise():
77
info = {
88
'family': 'kintex7',
99
'device': 'xc7k160t',
10-
'speed': '3',
10+
'speed': '-3',
1111
'package': 'fbg484'
1212
}
1313
assert get_info_ise('xc7k160t-3-fbg484') == info
1414
assert get_info_ise('xc7k160t-fbg484-3') == info
15+
info['speed'] = '-3l'
16+
assert get_info_ise('xc7k160t-3L-fbg484') == info
17+
assert get_info_ise('xc7k160t-fbg484-3L') == info
1518

1619

1720
def test_libero():
1821
info = {
1922
'family': 'SmartFusion2',
20-
'device': 'm2s010',
21-
'speed': '-1',
22-
'package': 'tq144',
23+
'device': 'm2s025t',
24+
'speed': 'STD',
25+
'package': 'fg484',
2326
'prange': 'COM'
2427
}
25-
assert get_info_libero('m2s010-1-tq144') == info
26-
assert get_info_libero('m2s010-tq144-1') == info
27-
info['speed'] = 'STD'
28-
assert get_info_libero('m2s010-tq144') == info
28+
assert get_info_libero('M2S025T-FG484') == info
29+
info['prange'] = 'IND'
30+
assert get_info_libero('M2S025T-FG484I') == info
31+
info['speed'] = '-1'
32+
info['prange'] = 'COM'
33+
assert get_info_libero('M2S025T-1FG484') == info
34+
assert get_info_libero('M2S025T-1-FG484') == info
35+
assert get_info_libero('M2S025T-FG484-1') == info
36+
info['prange'] = 'IND'
37+
assert get_info_libero('M2S025T-1FG484I') == info
38+
assert get_info_libero('M2S025T-1-FG484I') == info
39+
assert get_info_libero('M2S025T-FG484I-1') == info
40+
info['prange'] = 'MIL'
41+
assert get_info_libero('M2S025T-1FG484M') == info
42+
assert get_info_libero('M2S025T-1-FG484M') == info
43+
assert get_info_libero('M2S025T-FG484M-1') == info
44+
info = {
45+
'family': 'IGLOO2',
46+
'device': 'm2gl025',
47+
'speed': 'STD',
48+
'package': 'fg484',
49+
'prange': 'COM'
50+
}
51+
assert get_info_libero('M2GL025-FG484') == info
52+
info['prange'] = 'IND'
53+
assert get_info_libero('M2GL025-FG484I') == info
54+
info['speed'] = '-1'
55+
info['prange'] = 'COM'
56+
assert get_info_libero('M2GL025-1FG484') == info
57+
assert get_info_libero('M2GL025-1-FG484') == info
58+
assert get_info_libero('M2GL025-FG484-1') == info
59+
info['prange'] = 'IND'
60+
assert get_info_libero('M2GL025-1FG484I') == info
61+
assert get_info_libero('M2GL025-1-FG484I') == info
62+
assert get_info_libero('M2GL025-FG484I-1') == info
63+
info['prange'] = 'MIL'
64+
assert get_info_libero('M2GL025-1FG484M') == info
65+
assert get_info_libero('M2GL025-1-FG484M') == info
66+
assert get_info_libero('M2GL025-FG484M-1') == info
67+
info['prange'] = 'TGrade1'
68+
assert get_info_libero('M2GL025-1FG484T1') == info
69+
assert get_info_libero('M2GL025-1-FG484T1') == info
70+
assert get_info_libero('M2GL025-FG484T1-1') == info
71+
info = {
72+
'family': 'PolarFire',
73+
'device': 'mpf300ts_es',
74+
'speed': 'STD',
75+
'package': 'fg484',
76+
'prange': 'EXT'
77+
}
78+
assert get_info_libero('MPF300TS_ES-FG484E') == info
79+
info['prange'] = 'IND'
80+
assert get_info_libero('MPF300TS_ES-FG484I') == info
81+
info['speed'] = '-1'
82+
info['prange'] = 'EXT'
83+
assert get_info_libero('MPF300TS_ES-1FG484E') == info
84+
assert get_info_libero('MPF300TS_ES-1-FG484E') == info
85+
assert get_info_libero('MPF300TS_ES-FG484E-1') == info
86+
info['prange'] = 'IND'
87+
assert get_info_libero('MPF300TS_ES-1FG484I') == info
88+
assert get_info_libero('MPF300TS_ES-1-FG484I') == info
89+
assert get_info_libero('MPF300TS_ES-FG484I-1') == info
90+
info = {
91+
'family': 'PolarFireSoC',
92+
'device': 'mpfs025t',
93+
'speed': 'STD',
94+
'package': 'fcvg484',
95+
'prange': 'EXT'
96+
}
97+
assert get_info_libero('MPFS025T-FCVG484E') == info
98+
info['prange'] = 'IND'
99+
assert get_info_libero('MPFS025T-FCVG484I') == info
100+
info['speed'] = '-1'
101+
info['prange'] = 'EXT'
102+
assert get_info_libero('MPFS025T-1FCVG484E') == info
103+
assert get_info_libero('MPFS025T-1-FCVG484E') == info
104+
assert get_info_libero('MPFS025T-FCVG484E-1') == info
105+
info['prange'] = 'IND'
106+
assert get_info_libero('MPFS025T-1FCVG484I') == info
107+
assert get_info_libero('MPFS025T-1-FCVG484I') == info
108+
assert get_info_libero('MPFS025T-FCVG484I-1') == info
29109

30110

31111
def test_openflow():

0 commit comments

Comments
 (0)