Skip to content

Commit d94c979

Browse files
committed
back.rtlil: implement remaining format specifiers.
This requires a Yosys version from git. The requirement should be bumped to a proper release before Amaranth 0.5.
1 parent d3c5b95 commit d94c979

File tree

5 files changed

+160
-27
lines changed

5 files changed

+160
-27
lines changed

amaranth/back/rtlil.py

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1090,35 +1090,42 @@ def emit_print(self, cell_idx, cell):
10901090
args += chunk.value
10911091
if type is None:
10921092
type = "d"
1093-
if type == "x" or type == "X":
1094-
# TODO(yosys): "H" type
1093+
elif type == "x":
10951094
type = "h"
1096-
if type == "s":
1097-
# TODO(yosys): support for single unicode character?
1095+
elif type == "X":
1096+
type = "H"
1097+
elif type == "c":
1098+
type = "U"
1099+
elif type == "s":
10981100
type = "c"
10991101
width = spec["width"]
11001102
align = spec["align"]
11011103
if align is None:
1102-
align = ">" if type != "c" else "<"
1103-
if align == "=":
1104-
# TODO(yosys): "=" alignment
1105-
align = ">"
1104+
align = "<" if type in ("c", "U") else ">"
11061105
fill = spec["fill"]
1107-
if fill not in (" ", "0"):
1108-
# TODO(yosys): arbitrary fill
1109-
fill = " "
1110-
# TODO(yosys): support for options, grouping
1106+
if fill is None:
1107+
fill = ' '
1108+
if ord(fill) >= 0x80:
1109+
raise NotImplementedError(f"non-ASCII fill character {fill!r} is not supported in RTLIL")
11111110
sign = spec["sign"]
1112-
if sign != "+":
1113-
# TODO(yosys): support " " sign
1111+
if sign is None:
11141112
sign = ""
1115-
if type == "c":
1113+
if type in ("c", "U"):
11161114
signed = ""
11171115
elif chunk.signed:
11181116
signed = "s"
11191117
else:
11201118
signed = "u"
1121-
format.append(f"{{{len(chunk.value)}:{align}{fill}{width or ''}{type}{sign}{signed}}}")
1119+
show_base = "#" if spec["show_base"] and type != "d" else ""
1120+
grouping = spec["grouping"] or ""
1121+
if type == "U":
1122+
if align != "<" and width != 0:
1123+
format.append(fill * (width - 1))
1124+
format.append(f"{{{len(chunk.value)}:U}}")
1125+
if align == "<" and width != 0:
1126+
format.append(fill * (width - 1))
1127+
else:
1128+
format.append(f"{{{len(chunk.value)}:{align}{fill}{width or ''}{type}{sign}{show_base}{grouping}{signed}}}")
11221129
ports = {
11231130
"EN": self.sigspec(cell.en),
11241131
"ARGS": self.sigspec(_nir.Value(args)),

amaranth/back/verilog.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
def _convert_rtlil_text(rtlil_text, *, strip_internal_attrs=False, write_verilog_opts=()):
1111
# This version requirement needs to be synchronized with the one in pyproject.toml!
12-
yosys = find_yosys(lambda ver: ver >= (0, 38))
12+
yosys = find_yosys(lambda ver: ver >= (0, 39, 0, 165))
1313

1414
script = []
1515
script.append(f"read_ilang <<rtlil\n{rtlil_text}\nrtlil")

amaranth/hdl/_ast.py

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2691,7 +2691,8 @@ def __format__(self, format_desc):
26912691
(?P<align>[<>=^])
26922692
)?
26932693
(?P<sign>[-+ ])?
2694-
(?P<options>[#]?[0]?)
2694+
(?P<show_base>[#]?)
2695+
(?P<width_zero>[0]?)
26952696
(?P<width>[1-9][0-9]*)?
26962697
(?P<grouping>[_,])?
26972698
(?P<type>[bodxXcsn])?
@@ -2713,25 +2714,30 @@ def _parse_format_spec(spec: str, shape: Shape):
27132714
raise ValueError(f"Cannot print signed value with format specifier {match['type']!r}")
27142715
if match["align"] == "=":
27152716
raise ValueError(f"Alignment {match['align']!r} is not allowed with format specifier {match['type']!r}")
2716-
if "#" in match["options"]:
2717+
if match["show_base"]:
27172718
raise ValueError(f"Alternate form is not allowed with format specifier {match['type']!r}")
2718-
if "0" in match["options"]:
2719+
if match["width_zero"] != "":
27192720
raise ValueError(f"Zero fill is not allowed with format specifier {match['type']!r}")
27202721
if match["sign"] is not None:
27212722
raise ValueError(f"Sign is not allowed with format specifier {match['type']!r}")
27222723
if match["grouping"] is not None:
27232724
raise ValueError(f"Cannot specify {match['grouping']!r} with format specifier {match['type']!r}")
27242725
if match["type"] == "s" and shape.width % 8 != 0:
27252726
raise ValueError(f"Value width must be divisible by 8 with format specifier {match['type']!r}")
2727+
fill = match["fill"]
2728+
align = match["align"]
2729+
if match["width_zero"] and align is None:
2730+
fill = "0"
2731+
align = "="
27262732
return {
27272733
# Single character or None.
2728-
"fill": match["fill"],
2734+
"fill": fill,
27292735
# '<', '>', '=', or None. Cannot be '=' for types 'c' and 's'.
2730-
"align": match["align"],
2736+
"align": align,
27312737
# '-', '+', ' ', or None. Always None for types 'c' and 's'.
27322738
"sign": match["sign"],
2733-
# "", "#", "0", or "#0". Always "" for types 'c' and 's'.
2734-
"options": match["options"],
2739+
# A bool. Always False for types 'c' and 's'.
2740+
"show_base": match["show_base"] == "#",
27352741
# An int.
27362742
"width": int(match["width"]) if match["width"] is not None else 0,
27372743
# '_' or None. Always None for types 'c' and 's'.

pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ dependencies = [
2424
# - pyproject.toml: tool.pdm.dev-dependencies.test
2525
# - amaranth/back/verilog.py: _convert_rtlil_text
2626
# - docs/install.rst: yosys-version
27-
builtin-yosys = ["amaranth-yosys>=0.38"]
27+
builtin-yosys = ["amaranth-yosys>=0.39.0.165.post92"]
2828
remote-build = ["paramiko~=2.7"]
2929

3030
[project.scripts]
@@ -65,7 +65,7 @@ source-includes = [
6565
[tool.pdm.dev-dependencies]
6666
# This version requirement needs to be synchronized with the one in pyproject.toml above!
6767
test = [
68-
"yowasp-yosys>=0.38",
68+
"yowasp-yosys>=0.39.0.165.post92",
6969
"coverage",
7070
]
7171
docs = [

tests/test_back_rtlil.py

Lines changed: 121 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1889,6 +1889,127 @@ def test_assume_msg(self):
18891889
end
18901890
""")
18911891

1892+
def test_print_char(self):
1893+
i = Signal(21)
1894+
m = Module()
1895+
m.d.comb += [
1896+
Print(Format("{:c} {:-<5c} {:->5c}", i, i, i)),
1897+
]
1898+
self.assertRTLIL(m, [i], R"""
1899+
attribute \generator "Amaranth"
1900+
attribute \top 1
1901+
module \top
1902+
wire width 21 input 0 \i
1903+
wire width 1 $1
1904+
process $2
1905+
assign $1 [0] 1'0
1906+
assign $1 [0] 1'1
1907+
end
1908+
cell $print $3
1909+
parameter \FORMAT "{21:U} {21:U}---- ----{21:U}\n"
1910+
parameter \ARGS_WIDTH 63
1911+
parameter signed \PRIORITY 32'11111111111111111111111111111110
1912+
parameter \TRG_ENABLE 0
1913+
parameter \TRG_WIDTH 0
1914+
parameter \TRG_POLARITY 0
1915+
connect \EN $1 [0]
1916+
connect \ARGS { \i [20:0] \i [20:0] \i [20:0] }
1917+
connect \TRG { }
1918+
end
1919+
end
1920+
""")
1921+
1922+
def test_print_base(self):
1923+
i = Signal(8)
1924+
m = Module()
1925+
m.d.comb += [
1926+
Print(Format("{:b} {:o} {:d} {:x} {:X} {:#x} {:#d} {:#_x}", i, i, i, i, i, i, i, i)),
1927+
]
1928+
self.assertRTLIL(m, [i], R"""
1929+
attribute \generator "Amaranth"
1930+
attribute \top 1
1931+
module \top
1932+
wire width 8 input 0 \i
1933+
wire width 1 $1
1934+
process $2
1935+
assign $1 [0] 1'0
1936+
assign $1 [0] 1'1
1937+
end
1938+
cell $print $3
1939+
parameter \FORMAT "{8:> bu} {8:> ou} {8:> du} {8:> hu} {8:> Hu} {8:> h#u} {8:> du} {8:> h#_u}\n"
1940+
parameter \ARGS_WIDTH 64
1941+
parameter signed \PRIORITY 32'11111111111111111111111111111110
1942+
parameter \TRG_ENABLE 0
1943+
parameter \TRG_WIDTH 0
1944+
parameter \TRG_POLARITY 0
1945+
connect \EN $1 [0]
1946+
connect \ARGS { \i [7:0] \i [7:0] \i [7:0] \i [7:0] \i [7:0] \i [7:0] \i [7:0] \i [7:0] }
1947+
connect \TRG { }
1948+
end
1949+
end
1950+
""")
1951+
1952+
def test_print_sign(self):
1953+
i = Signal(8)
1954+
m = Module()
1955+
m.d.comb += [
1956+
Print(Format("{:5x} {:-5x} {:+5x} {: 5x}", i, i, i, i)),
1957+
]
1958+
self.assertRTLIL(m, [i], R"""
1959+
attribute \generator "Amaranth"
1960+
attribute \top 1
1961+
module \top
1962+
wire width 8 input 0 \i
1963+
wire width 1 $1
1964+
process $2
1965+
assign $1 [0] 1'0
1966+
assign $1 [0] 1'1
1967+
end
1968+
cell $print $3
1969+
parameter \FORMAT "{8:> 5hu} {8:> 5h-u} {8:> 5h+u} {8:> 5h u}\n"
1970+
parameter \ARGS_WIDTH 32
1971+
parameter signed \PRIORITY 32'11111111111111111111111111111110
1972+
parameter \TRG_ENABLE 0
1973+
parameter \TRG_WIDTH 0
1974+
parameter \TRG_POLARITY 0
1975+
connect \EN $1 [0]
1976+
connect \ARGS { \i [7:0] \i [7:0] \i [7:0] \i [7:0] }
1977+
connect \TRG { }
1978+
end
1979+
end
1980+
""")
1981+
1982+
def test_print_align(self):
1983+
i = Signal(8)
1984+
m = Module()
1985+
m.d.comb += [
1986+
Print(Format("{:<5x} {:>5x} {:=5x} {:05x} {:-<5x}", i, i, i, i, i)),
1987+
]
1988+
self.assertRTLIL(m, [i], R"""
1989+
attribute \generator "Amaranth"
1990+
attribute \top 1
1991+
module \top
1992+
wire width 8 input 0 \i
1993+
wire width 1 $1
1994+
process $2
1995+
assign $1 [0] 1'0
1996+
assign $1 [0] 1'1
1997+
end
1998+
cell $print $3
1999+
parameter \FORMAT "{8:< 5hu} {8:> 5hu} {8:= 5hu} {8:=05hu} {8:<-5hu}\n"
2000+
parameter \ARGS_WIDTH 40
2001+
parameter signed \PRIORITY 32'11111111111111111111111111111110
2002+
parameter \TRG_ENABLE 0
2003+
parameter \TRG_WIDTH 0
2004+
parameter \TRG_POLARITY 0
2005+
connect \EN $1 [0]
2006+
connect \ARGS { \i [7:0] \i [7:0] \i [7:0] \i [7:0] \i [7:0] }
2007+
connect \TRG { }
2008+
end
2009+
end
2010+
""")
2011+
2012+
18922013
class ComponentTestCase(RTLILTestCase):
18932014
def test_component(self):
18942015
class MyComponent(wiring.Component):
@@ -1907,4 +2028,3 @@ def elaborate(self, platform):
19072028
connect \o 8'00000000
19082029
end
19092030
""")
1910-

0 commit comments

Comments
 (0)