From 0f4eb23caa7874473dee3758fd73e9dc93bc1e78 Mon Sep 17 00:00:00 2001 From: RadicalRoman Date: Mon, 27 Mar 2023 14:33:12 -0700 Subject: [PATCH 1/8] Add coverage --- pyverilator/pyverilator.py | 1 + pyverilator/verilatorcpp.py | 1 + 2 files changed, 2 insertions(+) diff --git a/pyverilator/pyverilator.py b/pyverilator/pyverilator.py index 1daa160..9c640a3 100644 --- a/pyverilator/pyverilator.py +++ b/pyverilator/pyverilator.py @@ -434,6 +434,7 @@ def build(cls, top_verilog_file, verilog_path = [], build_dir = 'obj_dir', '-fPIC -shared --std=c++11 -DVL_USER_FINISH', '--trace', '--cc', + '--coverage', top_verilog_file, '--exe', verilator_cpp_wrapper_path] diff --git a/pyverilator/verilatorcpp.py b/pyverilator/verilatorcpp.py index d1eb111..9d39300 100644 --- a/pyverilator/verilatorcpp.py +++ b/pyverilator/verilatorcpp.py @@ -120,6 +120,7 @@ def function_definitions_cpp(top_module, inputs, outputs, internal_signals, json return Verilated::gotFinish(); }} void set_finished(bool b) {{ + Verilated::threadContextp()->coveragep()->write("coverage.dat"); Verilated::gotFinish(b); }} void set_vl_finish_callback(vl_finish_callback callback) {{ From 6ed975146584459b3dc46d3437413d896dc93e4b Mon Sep 17 00:00:00 2001 From: Jason Mitchell Date: Thu, 13 Apr 2023 15:21:07 -0700 Subject: [PATCH 2/8] Add multiple job support to build --- pyverilator/pyverilator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyverilator/pyverilator.py b/pyverilator/pyverilator.py index 9c640a3..1a4130d 100644 --- a/pyverilator/pyverilator.py +++ b/pyverilator/pyverilator.py @@ -490,7 +490,7 @@ def search_for_signal_decl(signal_type, line): # call make to build the pyverilator shared object make_args = ['make', '-C', build_dir, '-f', 'V%s.mk' % verilog_module_name, - 'LDFLAGS=-fPIC -shared'] + 'LDFLAGS=-fPIC -shared', '--jobs'] call_process(make_args, quiet=quiet) so_file = os.path.join(build_dir, 'V' + verilog_module_name) return cls(so_file, command_args=command_args) From 656bac50dc3f60bb6e3ae9bfd24488f5166f7454 Mon Sep 17 00:00:00 2001 From: Jason Mitchell Date: Thu, 13 Apr 2023 16:08:46 -0700 Subject: [PATCH 3/8] Add a way to capture the output of a build --- pyverilator/pyverilator.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/pyverilator/pyverilator.py b/pyverilator/pyverilator.py index 1a4130d..a0afc2a 100644 --- a/pyverilator/pyverilator.py +++ b/pyverilator/pyverilator.py @@ -6,6 +6,7 @@ import re import warnings import sys +import typing from keyword import iskeyword import pyverilator.verilatorcpp as template_cpp import tclwrapper @@ -337,12 +338,13 @@ def tick(self): self.write(0) self.write(1) -def call_process(args, quiet=False): +def call_process(args, quiet=False, output_stream: typing.TextIO = None): if quiet: subprocess.run(args, stderr=subprocess.PIPE, stdout=subprocess.PIPE, check=True) else: - subprocess.check_call(args) + subprocess.check_call(args, stderr=output_stream, + stdout=output_stream) class PyVerilator: """Python wrapper for verilator model. @@ -371,7 +373,8 @@ class PyVerilator: @classmethod def build(cls, top_verilog_file, verilog_path = [], build_dir = 'obj_dir', json_data = None, gen_only = False, quiet=False, - command_args=(), verilog_defines=()): + command_args=(), verilog_defines=(), + output_stream: typing.TextIO = None): """Build an object file from verilog and load it into python. Creates a folder build_dir in which it puts all the files necessary to create @@ -438,7 +441,7 @@ def build(cls, top_verilog_file, verilog_path = [], build_dir = 'obj_dir', top_verilog_file, '--exe', verilator_cpp_wrapper_path] - call_process(verilator_args) + call_process(verilator_args, output_stream=output_stream) # get inputs, outputs, and internal signals by parsing the generated verilator output inputs = [] @@ -491,7 +494,7 @@ def search_for_signal_decl(signal_type, line): # call make to build the pyverilator shared object make_args = ['make', '-C', build_dir, '-f', 'V%s.mk' % verilog_module_name, 'LDFLAGS=-fPIC -shared', '--jobs'] - call_process(make_args, quiet=quiet) + call_process(make_args, quiet=quiet, output_stream=output_stream) so_file = os.path.join(build_dir, 'V' + verilog_module_name) return cls(so_file, command_args=command_args) From 449c04b4beec3826977b041babb5ab8689ae1018 Mon Sep 17 00:00:00 2001 From: Jason Mitchell <126027232+radsemijmitchell@users.noreply.github.com> Date: Fri, 14 Apr 2023 15:09:38 -0700 Subject: [PATCH 4/8] Add limit on the ammount of jobs that can be created (#2) --- pyverilator/pyverilator.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pyverilator/pyverilator.py b/pyverilator/pyverilator.py index a0afc2a..0e9772c 100644 --- a/pyverilator/pyverilator.py +++ b/pyverilator/pyverilator.py @@ -7,6 +7,7 @@ import warnings import sys import typing +import multiprocessing from keyword import iskeyword import pyverilator.verilatorcpp as template_cpp import tclwrapper @@ -493,7 +494,7 @@ def search_for_signal_decl(signal_type, line): # call make to build the pyverilator shared object make_args = ['make', '-C', build_dir, '-f', 'V%s.mk' % verilog_module_name, - 'LDFLAGS=-fPIC -shared', '--jobs'] + 'LDFLAGS=-fPIC -shared', '--jobs', str(multiprocessing.cpu_count())] call_process(make_args, quiet=quiet, output_stream=output_stream) so_file = os.path.join(build_dir, 'V' + verilog_module_name) return cls(so_file, command_args=command_args) From 1f6026f1b7c03dc7664289cc0c3fcd6fda05ae76 Mon Sep 17 00:00:00 2001 From: Jason Mitchell <126027232+radsemijmitchell@users.noreply.github.com> Date: Fri, 21 Apr 2023 08:22:53 -0700 Subject: [PATCH 5/8] Add build and dist to gitignore --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 1f7c607..14143a4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ *.egg-info/ __pycache__/ -examples/build .* +build/ +dist/ From 3b8c7c3d8cc20645ae08a98ef638e090daa24ef3 Mon Sep 17 00:00:00 2001 From: zachbela Date: Tue, 9 May 2023 16:45:49 -0700 Subject: [PATCH 6/8] Added extra args to allow passing additional CPP files into Verilator via PyVerilator for DPI support --- pyverilator/pyverilator.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/pyverilator/pyverilator.py b/pyverilator/pyverilator.py index 0e9772c..4f3d64d 100644 --- a/pyverilator/pyverilator.py +++ b/pyverilator/pyverilator.py @@ -374,7 +374,7 @@ class PyVerilator: @classmethod def build(cls, top_verilog_file, verilog_path = [], build_dir = 'obj_dir', json_data = None, gen_only = False, quiet=False, - command_args=(), verilog_defines=(), + command_args=(), verilog_defines=(), cpp_files=[], output_stream: typing.TextIO = None): """Build an object file from verilog and load it into python. @@ -397,6 +397,8 @@ def build(cls, top_verilog_file, verilog_path = [], build_dir = 'obj_dir', ``command_args`` is passed to Verilator as its argv. It can be used to pass arguments to the $test$plusargs and $value$plusargs system tasks. + ``cpp_files`` allows us to include extra C++ files in Verilator builds. Necessary for DPI calls. + ``verilog_defines`` is a list of preprocessor defines; each entry should be a string, and defined macros with value should be specified as "MACRO=value". If compilation fails, this function raises a ``subprocess.CalledProcessError``. @@ -406,6 +408,8 @@ def build(cls, top_verilog_file, verilog_path = [], build_dir = 'obj_dir', raise TypeError('verilog_defines expects a list of strings') if isinstance(command_args, str): raise TypeError('command_args expects a list of strings') + if isinstance(cpp_files, str): + raise TypeError('cpp_files expects a list of strings') # get the module name from the verilog file name top_verilog_file_base = os.path.basename(top_verilog_file) @@ -439,8 +443,9 @@ def build(cls, top_verilog_file, verilog_path = [], build_dir = 'obj_dir', '--trace', '--cc', '--coverage', - top_verilog_file, - '--exe', + top_verilog_file] \ + + cpp_files \ + + ['--exe', verilator_cpp_wrapper_path] call_process(verilator_args, output_stream=output_stream) From 10f4654e3761b9404889acabe5ee735eab3fe529 Mon Sep 17 00:00:00 2001 From: zachbela Date: Thu, 18 May 2023 18:37:03 -0700 Subject: [PATCH 7/8] Added a raw args field for directly passing args --- pyverilator/pyverilator.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pyverilator/pyverilator.py b/pyverilator/pyverilator.py index 4f3d64d..35962c8 100644 --- a/pyverilator/pyverilator.py +++ b/pyverilator/pyverilator.py @@ -375,6 +375,7 @@ class PyVerilator: def build(cls, top_verilog_file, verilog_path = [], build_dir = 'obj_dir', json_data = None, gen_only = False, quiet=False, command_args=(), verilog_defines=(), cpp_files=[], + raw_args=[], output_stream: typing.TextIO = None): """Build an object file from verilog and load it into python. @@ -399,6 +400,8 @@ def build(cls, top_verilog_file, verilog_path = [], build_dir = 'obj_dir', ``cpp_files`` allows us to include extra C++ files in Verilator builds. Necessary for DPI calls. + ``raw_args`` allows us to pass arguments directly to the perl invocation of Verilator. + ``verilog_defines`` is a list of preprocessor defines; each entry should be a string, and defined macros with value should be specified as "MACRO=value". If compilation fails, this function raises a ``subprocess.CalledProcessError``. @@ -410,6 +413,8 @@ def build(cls, top_verilog_file, verilog_path = [], build_dir = 'obj_dir', raise TypeError('command_args expects a list of strings') if isinstance(cpp_files, str): raise TypeError('cpp_files expects a list of strings') + if isinstance(raw_args, str): + raise TypeError('raw_args expects a list of strings') # get the module name from the verilog file name top_verilog_file_base = os.path.basename(top_verilog_file) @@ -445,6 +450,7 @@ def build(cls, top_verilog_file, verilog_path = [], build_dir = 'obj_dir', '--coverage', top_verilog_file] \ + cpp_files \ + + raw_args \ + ['--exe', verilator_cpp_wrapper_path] call_process(verilator_args, output_stream=output_stream) From a9e998f1377f276fa8de8e13768182eaab24332b Mon Sep 17 00:00:00 2001 From: Katie Watson Date: Tue, 17 Oct 2023 18:47:09 -0700 Subject: [PATCH 8/8] Remove coverage --- pyverilator/pyverilator.py | 1 - pyverilator/verilatorcpp.py | 1 - 2 files changed, 2 deletions(-) diff --git a/pyverilator/pyverilator.py b/pyverilator/pyverilator.py index 35962c8..6b6d259 100644 --- a/pyverilator/pyverilator.py +++ b/pyverilator/pyverilator.py @@ -447,7 +447,6 @@ def build(cls, top_verilog_file, verilog_path = [], build_dir = 'obj_dir', '-fPIC -shared --std=c++11 -DVL_USER_FINISH', '--trace', '--cc', - '--coverage', top_verilog_file] \ + cpp_files \ + raw_args \ diff --git a/pyverilator/verilatorcpp.py b/pyverilator/verilatorcpp.py index 9d39300..d1eb111 100644 --- a/pyverilator/verilatorcpp.py +++ b/pyverilator/verilatorcpp.py @@ -120,7 +120,6 @@ def function_definitions_cpp(top_module, inputs, outputs, internal_signals, json return Verilated::gotFinish(); }} void set_finished(bool b) {{ - Verilated::threadContextp()->coveragep()->write("coverage.dat"); Verilated::gotFinish(b); }} void set_vl_finish_callback(vl_finish_callback callback) {{