plat, vendor: systematically escape net and file names in Tcl.
Before this commit, there was only occasional quoting of some names used in any Tcl files. (I'm not sure what I was thinking.) After this commit, any substs that may include Tcl special characters are escaped. This does not include build names (which are explicitly restricted to ASCII to avoid this problem), or attribute names (which are chosen from a predefined set). Ideally we'd use a more principled approach but Jinja2 does not support custom escaping mechanisms. Note that Vivado restricts clock names to a more restrictive set that forbids using Tcl special characters even when escaped. Fixes #375.
This commit is contained in:
parent
6e29fbcc61
commit
6cee280407
|
@ -368,6 +368,17 @@ class TemplatedPlatform(Platform):
|
|||
def hierarchy(signal, separator):
|
||||
return separator.join(name_map[signal][1:])
|
||||
|
||||
def ascii_escape(string):
|
||||
def escape_one(match):
|
||||
if match.group(1) is None:
|
||||
return match.group(2)
|
||||
else:
|
||||
return "_{:02x}_".format(ord(match.group(1)[0]))
|
||||
return "".join(escape_one(m) for m in re.finditer(r"([^A-Za-z0-9_])|(.)", string))
|
||||
|
||||
def tcl_escape(string):
|
||||
return "{" + re.sub(r"([{}\\])", r"\\\1", string) + "}"
|
||||
|
||||
def verbose(arg):
|
||||
if "NMIGEN_verbose" in os.environ:
|
||||
return arg
|
||||
|
@ -387,6 +398,8 @@ class TemplatedPlatform(Platform):
|
|||
trim_blocks=True, lstrip_blocks=True, undefined=jinja2.StrictUndefined)
|
||||
compiled.environment.filters["options"] = options
|
||||
compiled.environment.filters["hierarchy"] = hierarchy
|
||||
compiled.environment.filters["ascii_escape"] = ascii_escape
|
||||
compiled.environment.filters["tcl_escape"] = tcl_escape
|
||||
except jinja2.TemplateSyntaxError as e:
|
||||
e.args = ("{} (at {}:{})".format(e.message, origin, e.lineno),)
|
||||
raise
|
||||
|
|
18
nmigen/vendor/intel.py
vendored
18
nmigen/vendor/intel.py
vendored
|
@ -85,22 +85,22 @@ class IntelPlatform(TemplatedPlatform):
|
|||
{% endif %}
|
||||
|
||||
{% for file in platform.iter_extra_files(".v") -%}
|
||||
set_global_assignment -name VERILOG_FILE "{{file}}"
|
||||
set_global_assignment -name VERILOG_FILE {{file|tcl_escape}}
|
||||
{% endfor %}
|
||||
{% for file in platform.iter_extra_files(".sv") -%}
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE "{{file}}"
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE {{file|tcl_escape}}
|
||||
{% endfor %}
|
||||
{% for file in platform.iter_extra_files(".vhd", ".vhdl") -%}
|
||||
set_global_assignment -name VHDL_FILE "{{file}}"
|
||||
set_global_assignment -name VHDL_FILE {{file|tcl_escape}}
|
||||
{% endfor %}
|
||||
set_global_assignment -name VERILOG_FILE {{name}}.v
|
||||
set_global_assignment -name TOP_LEVEL_ENTITY {{name}}
|
||||
|
||||
set_global_assignment -name DEVICE {{platform.device}}{{platform.package}}{{platform.speed}}{{platform.suffix}}
|
||||
{% for port_name, pin_name, extras in platform.iter_port_constraints_bits() -%}
|
||||
set_location_assignment -to "{{port_name}}" PIN_{{pin_name}}
|
||||
{% for key, value in extras.items() -%}
|
||||
set_instance_assignment -to "{{port_name}}" -name {{key}} "{{value}}"
|
||||
{% for port_name, pin_name, attrs in platform.iter_port_constraints_bits() -%}
|
||||
set_location_assignment -to {{port_name|tcl_escape}} PIN_{{pin_name}}
|
||||
{% for key, value in attrs.items() -%}
|
||||
set_instance_assignment -to {{port_name|tcl_escape}} -name {{key}} {{value|tcl_escape}}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
|
||||
|
@ -109,9 +109,9 @@ class IntelPlatform(TemplatedPlatform):
|
|||
"{{name}}.sdc": r"""
|
||||
{% for net_signal, port_signal, frequency in platform.iter_clock_constraints() -%}
|
||||
{% if port_signal is not none -%}
|
||||
create_clock -name {{port_signal.name}} -period {{1000000000/frequency}} [get_ports {{port_signal.name}}]
|
||||
create_clock -name {{port_signal.name|tcl_escape}} -period {{1000000000/frequency}} [get_ports {{port_signal.name|tcl_escape}}]
|
||||
{% else -%}
|
||||
create_clock -name {{net_signal.name}} -period {{1000000000/frequency}} [get_nets {{net_signal|hierarchy("|")}}]
|
||||
create_clock -name {{net_signal.name|tcl_escape}} -period {{1000000000/frequency}} [get_nets {{net_signal|hierarchy("|")|tcl_escape}}]
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
""",
|
||||
|
|
14
nmigen/vendor/lattice_ecp5.py
vendored
14
nmigen/vendor/lattice_ecp5.py
vendored
|
@ -126,11 +126,11 @@ class LatticeECP5Platform(TemplatedPlatform):
|
|||
# {{autogenerated}}
|
||||
BLOCK ASYNCPATHS;
|
||||
BLOCK RESETPATHS;
|
||||
{% for port_name, pin_name, extras in platform.iter_port_constraints_bits() -%}
|
||||
{% for port_name, pin_name, attrs in platform.iter_port_constraints_bits() -%}
|
||||
LOCATE COMP "{{port_name}}" SITE "{{pin_name}}";
|
||||
{% if extras -%}
|
||||
{% if attrs -%}
|
||||
IOBUF PORT "{{port_name}}"
|
||||
{%- for key, value in extras.items() %} {{key}}={{value}}{% endfor %};
|
||||
{%- for key, value in attrs.items() %} {{key}}={{value}}{% endfor %};
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% for net_signal, port_signal, frequency in platform.iter_clock_constraints() -%}
|
||||
|
@ -206,7 +206,7 @@ class LatticeECP5Platform(TemplatedPlatform):
|
|||
-lpf {{name}}.lpf \
|
||||
-synthesis synplify
|
||||
{% for file in platform.iter_extra_files(".v", ".sv", ".vhd", ".vhdl") -%}
|
||||
prj_src add "{{file}}"
|
||||
prj_src add {{file|tcl_escape}}
|
||||
{% endfor %}
|
||||
prj_src add {{name}}.v
|
||||
prj_impl option top {{name}}
|
||||
|
@ -217,7 +217,7 @@ class LatticeECP5Platform(TemplatedPlatform):
|
|||
prj_run Translate -impl impl -forceAll
|
||||
prj_run Map -impl impl -forceAll
|
||||
prj_run PAR -impl impl -forceAll
|
||||
prj_run Export -impl "impl" -forceAll -task Bitgen
|
||||
prj_run Export -impl impl -forceAll -task Bitgen
|
||||
{{get_override("script_after_export")|default("# (script_after_export placeholder)")}}
|
||||
""",
|
||||
"{{name}}.lpf": r"""
|
||||
|
@ -234,9 +234,9 @@ class LatticeECP5Platform(TemplatedPlatform):
|
|||
"{{name}}.sdc": r"""
|
||||
{% for net_signal, port_signal, frequency in platform.iter_clock_constraints() -%}
|
||||
{% if port_signal is not none -%}
|
||||
create_clock -name {{port_signal.name}} -period {{1000000000/frequency}} [get_ports {{port_signal.name}}]
|
||||
create_clock -name {{port_signal.name|tcl_escape}} -period {{1000000000/frequency}} [get_ports {{port_signal.name|tcl_escape}}]
|
||||
{% else -%}
|
||||
create_clock -name {{net_signal.name}} -period {{1000000000/frequency}} [get_nets {{net_signal|hierarchy("/")}}]
|
||||
create_clock -name {{net_signal.name|tcl_escape}} -period {{1000000000/frequency}} [get_nets {{net_signal|hierarchy("/")|tcl_escape}}]
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{{get_override("add_constraints")|default("# (add_constraints placeholder)")}}
|
||||
|
|
6
nmigen/vendor/lattice_ice40.py
vendored
6
nmigen/vendor/lattice_ice40.py
vendored
|
@ -224,7 +224,7 @@ class LatticeICE40Platform(TemplatedPlatform):
|
|||
"{{name}}_syn.prj": r"""
|
||||
# {{autogenerated}}
|
||||
{% for file in platform.iter_extra_files(".v", ".sv", ".vhd", ".vhdl") -%}
|
||||
add_file -verilog {{file}}
|
||||
add_file -verilog {{file|tcl_escape}}
|
||||
{% endfor %}
|
||||
add_file -verilog {{name}}.v
|
||||
add_file -constraint {{name}}.sdc
|
||||
|
@ -246,9 +246,9 @@ class LatticeICE40Platform(TemplatedPlatform):
|
|||
# {{autogenerated}}
|
||||
{% for net_signal, port_signal, frequency in platform.iter_clock_constraints() -%}
|
||||
{% if port_signal is not none -%}
|
||||
create_clock -name {{port_signal.name}} -period {{1000000000/frequency}} [get_ports {{port_signal.name}}]
|
||||
create_clock -name {{port_signal.name|tcl_escape}} -period {{1000000000/frequency}} [get_ports {{port_signal.name|tcl_escape}}]
|
||||
{% else -%}
|
||||
create_clock -name {{net_signal.name}} -period {{1000000000/frequency}} [get_nets {{net_signal|hierarchy("/")}}]
|
||||
create_clock -name {{net_signal.name|tcl_escape}} -period {{1000000000/frequency}} [get_nets {{net_signal|hierarchy("/")|tcl_escape}}]
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{{get_override("add_constraints")|default("# (add_constraints placeholder)")}}
|
||||
|
|
12
nmigen/vendor/lattice_machxo2.py
vendored
12
nmigen/vendor/lattice_machxo2.py
vendored
|
@ -66,7 +66,7 @@ class LatticeMachXO2Platform(TemplatedPlatform):
|
|||
-lpf {{name}}.lpf \
|
||||
-synthesis synplify
|
||||
{% for file in platform.iter_extra_files(".v", ".sv", ".vhd", ".vhdl") -%}
|
||||
prj_src add "{{file}}"
|
||||
prj_src add {{file|tcl_escape}}
|
||||
{% endfor %}
|
||||
prj_src add {{name}}.v
|
||||
prj_impl option top {{name}}
|
||||
|
@ -84,11 +84,11 @@ class LatticeMachXO2Platform(TemplatedPlatform):
|
|||
# {{autogenerated}}
|
||||
BLOCK ASYNCPATHS;
|
||||
BLOCK RESETPATHS;
|
||||
{% for port_name, pin_name, extras in platform.iter_port_constraints_bits() -%}
|
||||
{% for port_name, pin_name, attrs in platform.iter_port_constraints_bits() -%}
|
||||
LOCATE COMP "{{port_name}}" SITE "{{pin_name}}";
|
||||
{% if extras -%}
|
||||
{% if attrs -%}
|
||||
IOBUF PORT "{{port_name}}"
|
||||
{%- for key, value in extras.items() %} {{key}}={{value}}{% endfor %};
|
||||
{%- for key, value in attrs.items() %} {{key}}={{value}}{% endfor %};
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{{get_override("add_preferences")|default("# (add_preferences placeholder)")}}
|
||||
|
@ -96,9 +96,9 @@ class LatticeMachXO2Platform(TemplatedPlatform):
|
|||
"{{name}}.sdc": r"""
|
||||
{% for net_signal, port_signal, frequency in platform.iter_clock_constraints() -%}
|
||||
{% if port_signal is not none -%}
|
||||
create_clock -name {{port_signal.name}} -period {{1000000000/frequency}} [get_ports {{port_signal.name}}]
|
||||
create_clock -name {{port_signal.name|tcl_escape}} -period {{1000000000/frequency}} [get_ports {{port_signal.name|tcl_escape}}]
|
||||
{% else -%}
|
||||
create_clock -name {{net_signal.name}} -period {{1000000000/frequency}} [get_nets {{net_signal|hierarchy("/")}}]
|
||||
create_clock -name {{net_signal.name|tcl_escape}} -period {{1000000000/frequency}} [get_nets {{net_signal|hierarchy("/")|tcl_escape}}]
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{{get_override("add_constraints")|default("# (add_constraints placeholder)")}}
|
||||
|
|
12
nmigen/vendor/xilinx_7series.py
vendored
12
nmigen/vendor/xilinx_7series.py
vendored
|
@ -78,12 +78,12 @@ class Xilinx7SeriesPlatform(TemplatedPlatform):
|
|||
# {{autogenerated}}
|
||||
create_project -force -name {{name}} -part {{platform.device}}{{platform.package}}-{{platform.speed}}{{"-" + platform.grade if platform.grade else ""}}
|
||||
{% for file in platform.iter_extra_files(".v", ".sv", ".vhd", ".vhdl") -%}
|
||||
add_files {{file}}
|
||||
add_files {{file|tcl_escape}}
|
||||
{% endfor %}
|
||||
add_files {{name}}.v
|
||||
read_xdc {{name}}.xdc
|
||||
{% for file in platform.iter_extra_files(".xdc") -%}
|
||||
read_xdc {{file}}
|
||||
read_xdc {{file|tcl_escape}}
|
||||
{% endfor %}
|
||||
{{get_override("script_after_read")|default("# (script_after_read placeholder)")}}
|
||||
synth_design -top {{name}}
|
||||
|
@ -128,16 +128,16 @@ class Xilinx7SeriesPlatform(TemplatedPlatform):
|
|||
"{{name}}.xdc": r"""
|
||||
# {{autogenerated}}
|
||||
{% for port_name, pin_name, attrs in platform.iter_port_constraints_bits() -%}
|
||||
set_property LOC {{pin_name}} [get_ports {{port_name}}]
|
||||
set_property LOC {{pin_name}} [get_ports {{port_name|tcl_escape}}]
|
||||
{% for attr_name, attr_value in attrs.items() -%}
|
||||
set_property {{attr_name}} {{attr_value}} [get_ports {{port_name}}]
|
||||
set_property {{attr_name}} {{attr_value|tcl_escape}} [get_ports {{port_name|tcl_escape}}]
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
{% for net_signal, port_signal, frequency in platform.iter_clock_constraints() -%}
|
||||
{% if port_signal is not none -%}
|
||||
create_clock -name {{port_signal.name}} -period {{1000000000/frequency}} [get_ports {{port_signal.name}}]
|
||||
create_clock -name {{port_signal.name|ascii_escape}} -period {{1000000000/frequency}} [get_ports {{port_signal.name|tcl_escape}}]
|
||||
{% else -%}
|
||||
create_clock -name {{net_signal.name}} -period {{1000000000/frequency}} [get_nets {{net_signal|hierarchy("/")}}]
|
||||
create_clock -name {{net_signal.name|ascii_escape}} -period {{1000000000/frequency}} [get_nets {{net_signal|hierarchy("/")|tcl_escape}}]
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{{get_override("add_constraints")|default("# (add_constraints placeholder)")}}
|
||||
|
|
12
nmigen/vendor/xilinx_ultrascale.py
vendored
12
nmigen/vendor/xilinx_ultrascale.py
vendored
|
@ -78,12 +78,12 @@ class XilinxUltraScalePlatform(TemplatedPlatform):
|
|||
# {{autogenerated}}
|
||||
create_project -force -name {{name}} -part {{platform.device}}-{{platform.package}}-{{platform.speed}}{{"-" + platform.grade if platform.grade else ""}}
|
||||
{% for file in platform.iter_extra_files(".v", ".sv", ".vhd", ".vhdl") -%}
|
||||
add_files {{file}}
|
||||
add_files {{file|tcl_escape}}
|
||||
{% endfor %}
|
||||
add_files {{name}}.v
|
||||
read_xdc {{name}}.xdc
|
||||
{% for file in platform.iter_extra_files(".xdc") -%}
|
||||
read_xdc {{file}}
|
||||
read_xdc {{file|tcl_escape}}
|
||||
{% endfor %}
|
||||
{{get_override("script_after_read")|default("# (script_after_read placeholder)")}}
|
||||
synth_design -top {{name}}
|
||||
|
@ -128,16 +128,16 @@ class XilinxUltraScalePlatform(TemplatedPlatform):
|
|||
"{{name}}.xdc": r"""
|
||||
# {{autogenerated}}
|
||||
{% for port_name, pin_name, attrs in platform.iter_port_constraints_bits() -%}
|
||||
set_property LOC {{pin_name}} [get_ports {{port_name}}]
|
||||
set_property LOC {{pin_name}} [get_ports {{port_name|tcl_escape}}]
|
||||
{% for attr_name, attr_value in attrs.items() -%}
|
||||
set_property {{attr_name}} {{attr_value}} [get_ports {{port_name}}]
|
||||
set_property {{attr_name}} {{attr_value|tcl_escape}} [get_ports {{port_name|tcl_escape}}]
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
{% for net_signal, port_signal, frequency in platform.iter_clock_constraints() -%}
|
||||
{% if port_signal is not none -%}
|
||||
create_clock -name {{port_signal.name}} -period {{1000000000/frequency}} [get_ports {{port_signal.name}}]
|
||||
create_clock -name {{port_signal.name|ascii_escape}} -period {{1000000000/frequency}} [get_ports {{port_signal.name|tcl_escape}}]
|
||||
{% else -%}
|
||||
create_clock -name {{net_signal.name}} -period {{1000000000/frequency}} [get_nets {{net_signal|hierarchy("/")}}]
|
||||
create_clock -name {{net_signal.name|ascii_escape}} -period {{1000000000/frequency}} [get_nets {{net_signal|hierarchy("/")|tcl_escape}}]
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{{get_override("add_constraints")|default("# (add_constraints placeholder)")}}
|
||||
|
|
Loading…
Reference in a new issue