Fixed clock port inference to use a more elaborate regex than "'clk' in port name". Added the possibility to force a port to be non-clock by setting the attribute CLOCK to 0. Signed-off-by: Maciej Kurc <mkurc@antmicro.com>
diff --git a/tests/clocks/README.md b/tests/clocks/README.md index e762b25..e969e29 100644 --- a/tests/clocks/README.md +++ b/tests/clocks/README.md
@@ -1,14 +1,14 @@ # `clocks` tests This directory contains test for the clock detection functionality for the -`v2x_to_model.py` tool. +`vlog_to_model.py` and `vlog_to_pbtype.py` tool. ## Detection of clock signals - - [ ] Signal is named `clk`. - - [ ] Signal has `clk` in the name. - - [ ] Manually set via the `(* CLOCK *)` Verilog attribute. + - [ ] Signal name matches the regexp `[a-z_]*clk[a-z0-9]*$` + - [ ] Manually set via the `(* CLOCK *)` or `(* CLOCK=1 *)` Verilog attribute. + - [ ] Manually cleared via the `(* CLOCK=0 *)` Verilog attribute. - [ ] Signal drives synchronous logic (IE flipflop). - [ ] Detection in recursive module includes.
diff --git a/tests/clocks/input_attr_not_clock/block.sim.v b/tests/clocks/input_attr_not_clock/block.sim.v new file mode 100644 index 0000000..ec59b5c --- /dev/null +++ b/tests/clocks/input_attr_not_clock/block.sim.v
@@ -0,0 +1,17 @@ +/* + * `input wire a` should be detected as a clock because it drives the flip + * flop. However, it has the attribute CLOCK set to 0 which should force it + * to be a regular input. + */ +module BLOCK(a, b, c); + (* CLOCK=0 *) + input wire a; + input wire b; + output wire c; + + reg r; + always @ ( posedge a ) begin + r <= b; + end + assign c = r; +endmodule
diff --git a/tests/clocks/input_attr_not_clock/golden.model.xml b/tests/clocks/input_attr_not_clock/golden.model.xml new file mode 100644 index 0000000..51ff8df --- /dev/null +++ b/tests/clocks/input_attr_not_clock/golden.model.xml
@@ -0,0 +1,11 @@ +<models xmlns:xi="http://www.w3.org/2001/XInclude"> + <model name="BLOCK"> + <input_ports> + <port clock="a" combinational_sink_ports="c" name="a"/> + <port clock="a" name="b"/> + </input_ports> + <output_ports> + <port clock="a" name="c"/> + </output_ports> + </model> +</models>
diff --git a/tests/clocks/input_attr_not_clock/golden.pb_type.xml b/tests/clocks/input_attr_not_clock/golden.pb_type.xml new file mode 100644 index 0000000..c748dd3 --- /dev/null +++ b/tests/clocks/input_attr_not_clock/golden.pb_type.xml
@@ -0,0 +1,7 @@ +<?xml version='1.0' encoding='utf-8'?> +<pb_type xmlns:xi="http://www.w3.org/2001/XInclude" name="BLOCK" num_pb="1"> + <blif_model>.subckt BLOCK</blif_model> + <input name="a" num_pins="1"/> + <input name="b" num_pins="1"/> + <output name="c" num_pins="1"/> +</pb_type>
diff --git a/tests/clocks/input_named_regex/block.sim.v b/tests/clocks/input_named_regex/block.sim.v new file mode 100644 index 0000000..3870d30 --- /dev/null +++ b/tests/clocks/input_named_regex/block.sim.v
@@ -0,0 +1,14 @@ +(* whitebox *) +module BLOCK( + input wire clk, + input wire Clk, + input wire CLK, + input wire clkX, + input wire clkBus, + input wire sys_clk, + input wire sys_clk10, + input wire regular_input, + output wire o +); + +endmodule
diff --git a/tests/clocks/input_named_regex/golden.model.xml b/tests/clocks/input_named_regex/golden.model.xml new file mode 100644 index 0000000..3f5edd2 --- /dev/null +++ b/tests/clocks/input_named_regex/golden.model.xml
@@ -0,0 +1,17 @@ +<models xmlns:xi="http://www.w3.org/2001/XInclude"> + <model name="BLOCK"> + <input_ports> + <port is_clock="1" name="CLK"/> + <port is_clock="1" name="Clk"/> + <port is_clock="1" name="clk"/> + <port is_clock="1" name="clkBus"/> + <port is_clock="1" name="clkX"/> + <port name="regular_input"/> + <port is_clock="1" name="sys_clk"/> + <port is_clock="1" name="sys_clk10"/> + </input_ports> + <output_ports> + <port name="o"/> + </output_ports> + </model> +</models>
diff --git a/tests/clocks/input_named_regex/golden.pb_type.xml b/tests/clocks/input_named_regex/golden.pb_type.xml new file mode 100644 index 0000000..2edf093 --- /dev/null +++ b/tests/clocks/input_named_regex/golden.pb_type.xml
@@ -0,0 +1,13 @@ +<?xml version='1.0' encoding='utf-8'?> +<pb_type xmlns:xi="http://www.w3.org/2001/XInclude" name="BLOCK" num_pb="1"> + <blif_model>.subckt BLOCK</blif_model> + <clock name="CLK" num_pins="1"/> + <clock name="Clk" num_pins="1"/> + <clock name="clk" num_pins="1"/> + <clock name="clkBus" num_pins="1"/> + <clock name="clkX" num_pins="1"/> + <clock name="sys_clk" num_pins="1"/> + <clock name="sys_clk10" num_pins="1"/> + <input name="regular_input" num_pins="1"/> + <output name="o" num_pins="1"/> +</pb_type>
diff --git a/v2x/vlog_to_model.py b/v2x/vlog_to_model.py index a4df516..3477de1 100755 --- a/v2x/vlog_to_model.py +++ b/v2x/vlog_to_model.py
@@ -3,7 +3,9 @@ Convert a Verilog simulation model to a VPR `model.xml` The following Verilog attributes are considered on ports: - - `(* CLOCK *)` : force a given port to be a clock + - `(* CLOCK *)` or `(* CLOCK=1 *)` : force a given port to be a clock + + - `(* CLOCK=0 *)` : force a given port not to be a clock - `(* ASSOC_CLOCK="RDCLK" *)` : force a port's associated clock to a given value @@ -26,6 +28,7 @@ from .yosys import run from .yosys.json import YosysJSON +from .yosys import utils as utils from .xmlinc import xmlinc @@ -173,6 +176,13 @@ for name, width, bits, iodir in ports: nocomb = tmod.net_attr(name, "NO_COMB") + + is_clock = name in clocks or utils.is_clock_name(name) + + port_attrs = tmod.port_attrs(name) + if "CLOCK" in port_attrs: + is_clock = int(port_attrs["CLOCK"]) != 0 + attrs = dict(name=name) sinks = run.get_combinational_sinks(infiles, top, name) @@ -183,7 +193,7 @@ # FIXME: Check if ignoring clock for "combination_sink_ports" # is a valid thing to do. - if name in clocks or "clk" in name.lower(): + if is_clock: attrs["is_clock"] = "1" else: clks = list()
diff --git a/v2x/vlog_to_pbtype.py b/v2x/vlog_to_pbtype.py index d109dfb..6f8d897 100755 --- a/v2x/vlog_to_pbtype.py +++ b/v2x/vlog_to_pbtype.py
@@ -44,7 +44,9 @@ with this wire The following are allowed on ports: - - `(* CLOCK *)` : force a given port to be a clock + - `(* CLOCK *)` or `(* CLOCK=1 *)` : force a given port to be a clock + + - `(* CLOCK=0 *)` : force a given port not to be a clock - `(* ASSOC_CLOCK="RDCLK" *)` : force a port's associated clock to a given value @@ -68,6 +70,7 @@ from .yosys import run from .yosys.json import YosysJSON +from .yosys import utils as utils from .xmlinc import xmlinc # noqa: E402 @@ -808,7 +811,22 @@ ET.SubElement(pb_type_xml, "pb_class", {}).text = pb_attrs["class"] # Create the pins for this pb_type - clocks = run.list_clocks(infiles, mod.name) + clocks = set(run.list_clocks(infiles, mod.name)) + + # Add extra clocks inferred from port names + # Mask out clocks with the attribute "CLOCK" not equal to 1 + for name, width, bits, iodir in mod.ports: + port_attrs = mod.port_attrs(name) + + is_clock = utils.is_clock_name(name) + if "CLOCK" in port_attrs: + is_clock = int(port_attrs["CLOCK"]) != 0 + + if is_clock: + clocks.add(name) + else: + clocks.discard(name) + make_ports(clocks, mod, pb_type_xml, "clocks") make_ports(clocks, mod, pb_type_xml, "inputs") make_ports(clocks, mod, pb_type_xml, "outputs")
diff --git a/v2x/yosys/run.py b/v2x/yosys/run.py index 9b30c79..5bf3f6a 100755 --- a/v2x/yosys/run.py +++ b/v2x/yosys/run.py
@@ -236,7 +236,7 @@ """ return do_select( infiles, module, - "c:* %x:+[CLK]:+[clk]:+[clock]:+[CLOCK] a:CLOCK=1 %u c:* %d x:* %i" + "c:* %x:+[CLK]:+[clk]:+[clock]:+[CLOCK] c:* %d x:* %i" )
diff --git a/v2x/yosys/utils.py b/v2x/yosys/utils.py index 722ac9b..4383161 100644 --- a/v2x/yosys/utils.py +++ b/v2x/yosys/utils.py
@@ -1,11 +1,22 @@ #!/usr/bin/env python3 import re -"""The JSON Yosys outputs isn't acutally compliant JSON, as it contains C-style -comments. These must be stripped.""" + +CLOCK_NAME_REGEX = re.compile(r"[a-z_]*clk[a-z0-9]*$") def strip_yosys_json(text): + """The JSON Yosys outputs isn't acutally compliant JSON, as it contains C-style + comments. These must be stripped.""" stripped = re.sub(r'\\\n', '', text) stripped = re.sub(r'//.*\n', '\n', stripped) stripped = re.sub(r'/\*.*\*/', '', stripped) return stripped + + +def is_clock_name(name): + """ + Returns true if the port name correspond to a clock according to arbitrary + regular expressions. + """ + match = CLOCK_NAME_REGEX.match(name.lower()) + return match is not None