From 6216e45edae11fa3cc6e45a65762e5c215af0904 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 27 Sep 2019 12:50:20 -0700 Subject: Add latch test modified from #1363 --- tests/xilinx/latches.v | 58 +++++++++++++++++++++++++++++++++++++++++++++++++ tests/xilinx/latches.ys | 15 +++++++++++++ 2 files changed, 73 insertions(+) create mode 100644 tests/xilinx/latches.v create mode 100644 tests/xilinx/latches.ys (limited to 'tests') diff --git a/tests/xilinx/latches.v b/tests/xilinx/latches.v new file mode 100644 index 000000000..83bad7f35 --- /dev/null +++ b/tests/xilinx/latches.v @@ -0,0 +1,58 @@ +module latchp + ( input d, en, output reg q ); + always @* + if ( en ) + q <= d; +endmodule + +module latchn + ( input d, en, output reg q ); + always @* + if ( !en ) + q <= d; +endmodule + +module latchsr + ( input d, en, clr, pre, output reg q ); + always @* + if ( clr ) + q <= 1'b0; + else if ( pre ) + q <= 1'b1; + else if ( en ) + q <= d; +endmodule + + +module top ( +input clk, +input clr, +input pre, +input a, +output b,b1,b2 +); + + +latchp u_latchp ( + .en (clk ), + .d (a ), + .q (b ) + ); + + +latchn u_latchn ( + .en (clk ), + .d (a ), + .q (b1 ) + ); + + +latchsr u_latchsr ( + .en (clk ), + .clr (clr), + .pre (pre), + .d (a ), + .q (b2 ) + ); + +endmodule diff --git a/tests/xilinx/latches.ys b/tests/xilinx/latches.ys new file mode 100644 index 000000000..ac1102896 --- /dev/null +++ b/tests/xilinx/latches.ys @@ -0,0 +1,15 @@ +read_verilog latches.v + +proc +flatten +equiv_opt -assert -run :prove -map +/xilinx/cells_sim.v synth_xilinx # equivalency check +async2sync +equiv_opt -assert -run prove: -map +/xilinx/cells_sim.v synth_xilinx # equivalency check + +design -load preopt +synth_xilinx +cd top +select -assert-count 1 t:LUT1 +select -assert-count 2 t:LUT3 +select -assert-count 3 t:LDCE +select -assert-none t:LUT1 t:LUT3 t:LDCE %% t:* %D -- cgit v1.2.3 From 99a7f39084cf4b9cd21e2a1e4f4a842993dfd147 Mon Sep 17 00:00:00 2001 From: whitequark Date: Thu, 26 Sep 2019 03:57:16 +0000 Subject: rpc: new frontend. A new pass, connect_rpc, allows any HDL frontend that can read/write JSON from/to stdin/stdout or an unix socket or a named pipe to participate in elaboration as a first class citizen, such that any other HDL supported by Yosys directly or indirectly can transparently instantiate modules handled by this frontend. Recognizing that many HDL frontends emit Verilog, it allows the RPC frontend to direct Yosys to process the result of instantiation via any built-in Yosys frontend. The resulting RTLIL is then hygienically integrated into the overall design. --- tests/rpc/.gitignore | 1 + tests/rpc/design.v | 8 ++++ tests/rpc/exec.ys | 5 ++ tests/rpc/frontend.py | 126 ++++++++++++++++++++++++++++++++++++++++++++++++++ tests/rpc/run-test.sh | 6 +++ tests/rpc/unix.ys | 6 +++ 6 files changed, 152 insertions(+) create mode 100644 tests/rpc/.gitignore create mode 100644 tests/rpc/design.v create mode 100644 tests/rpc/exec.ys create mode 100644 tests/rpc/frontend.py create mode 100755 tests/rpc/run-test.sh create mode 100644 tests/rpc/unix.ys (limited to 'tests') diff --git a/tests/rpc/.gitignore b/tests/rpc/.gitignore new file mode 100644 index 000000000..397b4a762 --- /dev/null +++ b/tests/rpc/.gitignore @@ -0,0 +1 @@ +*.log diff --git a/tests/rpc/design.v b/tests/rpc/design.v new file mode 100644 index 000000000..80f1dac1a --- /dev/null +++ b/tests/rpc/design.v @@ -0,0 +1,8 @@ +module top(input [3:0] i, output [3:0] o); + python_inv #( + .width(4) + ) inv ( + .i(i), + .o(o), + ); +endmodule diff --git a/tests/rpc/exec.ys b/tests/rpc/exec.ys new file mode 100644 index 000000000..b46009fb9 --- /dev/null +++ b/tests/rpc/exec.ys @@ -0,0 +1,5 @@ +connect_rpc -exec python3 frontend.py stdio +read_verilog design.v +hierarchy -top top +flatten +select -assert-count 1 t:$neg diff --git a/tests/rpc/frontend.py b/tests/rpc/frontend.py new file mode 100644 index 000000000..eff41738a --- /dev/null +++ b/tests/rpc/frontend.py @@ -0,0 +1,126 @@ +def modules(): + return ["python_inv"] + +def derive(module, parameters): + assert module == r"python_inv" + if parameters.keys() != {r"\width"}: + raise ValueError("Invalid parameters") + return "ilang", r""" +module \impl + wire width {width:d} input 1 \i + wire width {width:d} output 2 \o + cell $neg $0 + parameter \A_SIGNED 1'0 + parameter \A_WIDTH 32'{width:b} + parameter \Y_WIDTH 32'{width:b} + connect \A \i + connect \Y \o + end +end +module \python_inv + wire width {width:d} input 1 \i + wire width {width:d} output 2 \o + cell \impl $0 + connect \i \i + connect \o \o + end +end +""".format(width=parameters[r"\width"]) + +# ---------------------------------------------------------------------------- + +import json +import argparse +import sys, socket, os +try: + import msvcrt, win32pipe, win32file +except ImportError: + msvcrt = win32pipe = win32file = None + +def map_parameter(parameter): + if parameter["type"] == "unsigned": + return int(parameter["value"], 2) + if parameter["type"] == "signed": + width = len(parameter["value"]) + value = int(parameter["value"], 2) + if value & (1 << (width - 1)): + value = -((1 << width) - value) + return value + if parameter["type"] == "string": + return parameter["value"] + if parameter["type"] == "real": + return float(parameter["value"]) + +def call(input_json): + input = json.loads(input_json) + if input["method"] == "modules": + return json.dumps({"modules": modules()}) + if input["method"] == "derive": + try: + frontend, source = derive(input["module"], + {name: map_parameter(value) for name, value in input["parameters"].items()}) + return json.dumps({"frontend": frontend, "source": source}) + except ValueError as e: + return json.dumps({"error": str(e)}) + +def main(): + parser = argparse.ArgumentParser() + modes = parser.add_subparsers(dest="mode") + mode_stdio = modes.add_parser("stdio") + if os.name == "posix": + mode_path = modes.add_parser("unix-socket") + if os.name == "nt": + mode_path = modes.add_parser("named-pipe") + mode_path.add_argument("path") + args = parser.parse_args() + + if args.mode == "stdio": + while True: + input = sys.stdin.readline() + if not input: break + sys.stdout.write(call(input) + "\n") + sys.stdout.flush() + + if args.mode == "unix-socket": + sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + sock.bind(args.path) + try: + sock.listen(1) + conn, addr = sock.accept() + file = conn.makefile("rw") + while True: + input = file.readline() + if not input: break + file.write(call(input) + "\n") + file.flush() + finally: + sock.close() + os.unlink(args.path) + + if args.mode == "named-pipe": + pipe = win32pipe.CreateNamedPipe(args.path, win32pipe.PIPE_ACCESS_DUPLEX, + win32pipe.PIPE_TYPE_BYTE|win32pipe.PIPE_READMODE_BYTE|win32pipe.PIPE_WAIT, + 1, 4096, 4096, 0, None) + win32pipe.ConnectNamedPipe(pipe, None) + try: + while True: + input = b"" + while not input.endswith(b"\n"): + result, data = win32file.ReadFile(pipe, 4096) + assert result == 0 + input += data + assert not b"\n" in input or input.endswith(b"\n") + output = (call(input.decode("utf-8")) + "\n").encode("utf-8") + length = len(output) + while length > 0: + result, done = win32file.WriteFile(pipe, output) + assert result == 0 + length -= done + except win32file.error as e: + if e.args[0] == 109: # ERROR_BROKEN_PIPE + pass + else: + raise + +if __name__ == "__main__": + main() diff --git a/tests/rpc/run-test.sh b/tests/rpc/run-test.sh new file mode 100755 index 000000000..44ce7e674 --- /dev/null +++ b/tests/rpc/run-test.sh @@ -0,0 +1,6 @@ +#!/bin/bash +set -e +for x in *.ys; do + echo "Running $x.." + ../../yosys -ql ${x%.ys}.log $x +done diff --git a/tests/rpc/unix.ys b/tests/rpc/unix.ys new file mode 100644 index 000000000..cc7ec14ab --- /dev/null +++ b/tests/rpc/unix.ys @@ -0,0 +1,6 @@ +!python3 frontend.py unix-socket frontend.sock & sleep 0.1 +connect_rpc -path frontend.sock +read_verilog design.v +hierarchy -top top +flatten +select -assert-count 1 t:$neg -- cgit v1.2.3