diff options
author | Rupert Swarbrick <rswarbrick@gmail.com> | 2020-05-21 17:36:29 +0100 |
---|---|---|
committer | Zachary Snow <zachary.j.snow@gmail.com> | 2021-07-16 09:31:39 -0400 |
commit | 414154dd275b8cf9f0ffa071d12fc20fd6fee503 (patch) | |
tree | e5ee5f5f106219322b4b4091a2ec2a6e801ead83 /tests/bind | |
parent | 2db41375141dd8098edac134e09b962a5b0821ab (diff) | |
download | yosys-414154dd275b8cf9f0ffa071d12fc20fd6fee503.tar.gz yosys-414154dd275b8cf9f0ffa071d12fc20fd6fee503.tar.bz2 yosys-414154dd275b8cf9f0ffa071d12fc20fd6fee503.zip |
Add support for parsing the SystemVerilog 'bind' construct
This doesn't do anything useful yet: the patch just adds support for
the syntax to the lexer and parser and adds some tests to check the
syntax parses properly. This generates AST nodes, but doesn't yet
generate RTLIL.
Since our existing hierarchical_identifier parser doesn't allow bit
selects (so you can't do something like foo[1].bar[2].baz), I've also
not added support for a trailing bit select (the "constant_bit_select"
non-terminal in "bind_target_instance" in the spec). If we turn out to
need this in future, we'll want to augment hierarchical_identifier and
its other users too.
Note that you can't easily use the BNF from the spec:
bind_directive ::=
"bind" bind_target_scope [ : bind_target_instance_list]
bind_instantiation ;
| "bind" bind_target_instance bind_instantiation ;
even if you fix the lookahead problem, because code like this matches
both branches in the BNF:
bind a b b_i (.*);
The problem is that 'a' could either be a module name or a degenerate
hierarchical reference. This seems to be a genuine syntactic
ambiguity, which the spec resolves (p739) by saying that we have to
wait until resolution time (the hierarchy pass) and take whatever is
defined, treating 'a' as an instance name if it names both an instance
and a module.
To keep the parser simple, it currently accepts this invalid syntax:
bind a.b : c d e (.*);
This is invalid because we're in the first branch of the BNF above, so
the "a.b" term should match bind_target_scope: a module or interface
identifier, not an arbitrary hierarchical identifier.
This will fail in the hierarchy pass (when it's implemented in a
future patch).
Diffstat (limited to 'tests/bind')
-rw-r--r-- | tests/bind/.gitignore | 2 | ||||
-rw-r--r-- | tests/bind/basic.sv | 20 | ||||
-rw-r--r-- | tests/bind/basic.ys | 1 | ||||
-rw-r--r-- | tests/bind/cell_list.sv | 26 | ||||
-rw-r--r-- | tests/bind/cell_list.ys | 1 | ||||
-rw-r--r-- | tests/bind/hier.sv | 20 | ||||
-rw-r--r-- | tests/bind/hier.ys | 1 | ||||
-rw-r--r-- | tests/bind/inst_list.sv | 24 | ||||
-rw-r--r-- | tests/bind/inst_list.ys | 1 | ||||
-rw-r--r-- | tests/bind/param.sv | 26 | ||||
-rw-r--r-- | tests/bind/param.ys | 1 | ||||
-rwxr-xr-x | tests/bind/run-test.sh | 20 | ||||
-rw-r--r-- | tests/bind/toplevel.sv | 20 | ||||
-rw-r--r-- | tests/bind/toplevel.ys | 1 |
14 files changed, 164 insertions, 0 deletions
diff --git a/tests/bind/.gitignore b/tests/bind/.gitignore new file mode 100644 index 000000000..8355de9dc --- /dev/null +++ b/tests/bind/.gitignore @@ -0,0 +1,2 @@ +*.log +run-test.mk diff --git a/tests/bind/basic.sv b/tests/bind/basic.sv new file mode 100644 index 000000000..ce0d04c48 --- /dev/null +++ b/tests/bind/basic.sv @@ -0,0 +1,20 @@ +// A basic example of the bind construct + +module foo (input logic a, input logic b, output logic c); + // Magic happens here... +endmodule + +module bar (input a, input b, output c); + assign c = a ^ b; +endmodule + +module top (); + logic u, v, w; + foo foo_i (.a (u), .b (v), .c (w)); + + bind foo bar bound_i (.*); + + always_comb begin + assert(w == u ^ v); + end +endmodule diff --git a/tests/bind/basic.ys b/tests/bind/basic.ys new file mode 100644 index 000000000..266fa4e48 --- /dev/null +++ b/tests/bind/basic.ys @@ -0,0 +1 @@ +read_verilog -sv basic.sv diff --git a/tests/bind/cell_list.sv b/tests/bind/cell_list.sv new file mode 100644 index 000000000..c0da13d29 --- /dev/null +++ b/tests/bind/cell_list.sv @@ -0,0 +1,26 @@ +// An example of specifying multiple bind instances in a single directive. This +// also uses explicit bound names. + +module foo (input logic a0, input logic b0, output logic c0, + input logic a1, input logic b1, output logic c1); + // Magic happens here... +endmodule + +module bar (input a, input b, output c); + assign c = a ^ b; +endmodule + +module top (); + logic u0, v0, w0; + logic u1, v1, w1; + + foo foo0 (.a0 (u0), .b0 (v0), .c0 (w0), + .a1 (u1), .b1 (v1), .c1 (w1)); + + bind foo bar bar0 (.a(a0), .b(b0), .c(c0)), bar1 (.a(a1), .b(b1), .c(c1)); + + always_comb begin + assert(w0 == u0 ^ v0); + assert(w1 == u1 ^ v1); + end +endmodule diff --git a/tests/bind/cell_list.ys b/tests/bind/cell_list.ys new file mode 100644 index 000000000..9afd9a941 --- /dev/null +++ b/tests/bind/cell_list.ys @@ -0,0 +1 @@ +read_verilog -sv cell_list.sv diff --git a/tests/bind/hier.sv b/tests/bind/hier.sv new file mode 100644 index 000000000..fd3bc62b8 --- /dev/null +++ b/tests/bind/hier.sv @@ -0,0 +1,20 @@ +// An example of the bind construct using a hierarchical reference starting with $root + +module foo (input logic a, input logic b, output logic c); + // Magic happens here... +endmodule + +module bar (input a, input b, output c); + assign c = a ^ b; +endmodule + +module top (); + logic u, v, w; + foo foo_i (.a (u), .b (v), .c (w)); + + always_comb begin + assert(w == u ^ v); + end +endmodule + +bind $root.top.foo_i bar bound_i (.*); diff --git a/tests/bind/hier.ys b/tests/bind/hier.ys new file mode 100644 index 000000000..c19fba100 --- /dev/null +++ b/tests/bind/hier.ys @@ -0,0 +1 @@ +read_verilog -sv hier.sv diff --git a/tests/bind/inst_list.sv b/tests/bind/inst_list.sv new file mode 100644 index 000000000..e0077caec --- /dev/null +++ b/tests/bind/inst_list.sv @@ -0,0 +1,24 @@ +// An example of specifying multiple bind targets with an instance list + +module foo (input logic a, input logic b, output logic c); + // Magic happens here... +endmodule + +module bar (input a, input b, output c); + assign c = a ^ b; +endmodule + +module top (); + logic u0, v0, w0; + logic u1, v1, w1; + + foo foo0 (.a (u0), .b (v0), .c (w0)); + foo foo1 (.a (u1), .b (v1), .c (w1)); + + bind foo : foo0, foo1 bar bound_i (.*); + + always_comb begin + assert(w0 == u0 ^ v0); + assert(w1 == u1 ^ v1); + end +endmodule diff --git a/tests/bind/inst_list.ys b/tests/bind/inst_list.ys new file mode 100644 index 000000000..ac1385b83 --- /dev/null +++ b/tests/bind/inst_list.ys @@ -0,0 +1 @@ +read_verilog -sv inst_list.sv diff --git a/tests/bind/param.sv b/tests/bind/param.sv new file mode 100644 index 000000000..c7793527a --- /dev/null +++ b/tests/bind/param.sv @@ -0,0 +1,26 @@ +// An example showing how parameters get inferred when binding + +module foo (input logic a, input logic b, output logic c); + parameter doit = 1; + + // Magic happens here... +endmodule + +module bar (input a, input b, output c); + parameter doit = 1; + + assign c = doit ? a ^ b : 0; +endmodule + +module top (input u0, input v0, output w0, + input u1, input v1, output w1); + foo #(.doit (0)) foo0 (.a (u0), .b (v0), .c (w0)); + foo #(.doit (1)) foo1 (.a (u1), .b (v1), .c (w1)); + + bind foo bar #(.doit (doit)) bound_i (.*); + + always_comb begin + assert (w0 == '0); + assert (w1 == u1 ^ v1); + end +endmodule diff --git a/tests/bind/param.ys b/tests/bind/param.ys new file mode 100644 index 000000000..a43d05759 --- /dev/null +++ b/tests/bind/param.ys @@ -0,0 +1 @@ +read_verilog -sv param.sv diff --git a/tests/bind/run-test.sh b/tests/bind/run-test.sh new file mode 100755 index 000000000..ea56b70f0 --- /dev/null +++ b/tests/bind/run-test.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash +set -e +{ +echo "all::" +for x in *.ys; do + echo "all:: run-$x" + echo "run-$x:" + echo " @echo 'Running $x..'" + echo " @../../yosys -ql ${x%.ys}.log $x" +done +for s in *.sh; do + if [ "$s" != "run-test.sh" ]; then + echo "all:: run-$s" + echo "run-$s:" + echo " @echo 'Running $s..'" + echo " @bash $s" + fi +done +} > run-test.mk +exec ${MAKE:-make} -f run-test.mk diff --git a/tests/bind/toplevel.sv b/tests/bind/toplevel.sv new file mode 100644 index 000000000..328edcf67 --- /dev/null +++ b/tests/bind/toplevel.sv @@ -0,0 +1,20 @@ +// The bind construct occurring at top-level in the script + +module foo (input logic a, input logic b, output logic c); + // Magic happens here... +endmodule + +module bar (input a, input b, output c); + assign c = a ^ b; +endmodule + +module top (); + logic u, v, w; + foo foo_i (.a (u), .b (v), .c (w)); + + always_comb begin + assert(w == u ^ v); + end +endmodule + +bind top.foo_i bar bound_i (.*); diff --git a/tests/bind/toplevel.ys b/tests/bind/toplevel.ys new file mode 100644 index 000000000..11c0ada19 --- /dev/null +++ b/tests/bind/toplevel.ys @@ -0,0 +1 @@ +read_verilog -sv toplevel.sv |