From b39d5058312d657cdc2975a96d2da121f3888dea Mon Sep 17 00:00:00 2001 From: Kelvin Chung Date: Tue, 30 Apr 2024 11:26:08 +0100 Subject: [PATCH 1/6] Improve index handling in Bits and Signal classes --- pymtl3/datatypes/PythonBits.py | 2 ++ pymtl3/dsl/Connectable.py | 2 ++ 2 files changed, 4 insertions(+) diff --git a/pymtl3/datatypes/PythonBits.py b/pymtl3/datatypes/PythonBits.py index 33bd47f23..f65853800 100644 --- a/pymtl3/datatypes/PythonBits.py +++ b/pymtl3/datatypes/PythonBits.py @@ -133,6 +133,8 @@ def __getitem__( self, idx ): raise IndexError( "Index cannot contain step" ) try: start, stop = int(idx.start or 0), int(idx.stop or self._nbits) + if start is None: start = 0 + if stop is None: stop = self._nbits assert 0 <= start < stop <= self._nbits except: raise IndexError( f"Invalid access: [{idx.start}:{idx.stop}] in a Bits{self._nbits} instance" ) diff --git a/pymtl3/dsl/Connectable.py b/pymtl3/dsl/Connectable.py index 6a8683251..910c21ded 100644 --- a/pymtl3/dsl/Connectable.py +++ b/pymtl3/dsl/Connectable.py @@ -261,6 +261,8 @@ def __getitem__( s, idx ): start, stop = idx, idx + 1 elif isinstance( idx, slice ): start, stop = idx.start, idx.stop + if start is None: start = 0 + if stop is None: stop = s._dsl.Type.nbits else: assert False, f"The slice {idx} is invalid" if s._dsl.slice is None: From d0bc16ead0efc2e88aec77ab6de3a659c1db4999 Mon Sep 17 00:00:00 2001 From: Kelvin Chung Date: Tue, 30 Apr 2024 16:12:32 +0100 Subject: [PATCH 2/6] Adding test --- pymtl3/datatypes/test/bits_test.py | 6 ++++++ pymtl3/dsl/test/Slicing_test.py | 21 ++++++++++++++++++--- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/pymtl3/datatypes/test/bits_test.py b/pymtl3/datatypes/test/bits_test.py index 242e560ed..4943b66fe 100644 --- a/pymtl3/datatypes/test/bits_test.py +++ b/pymtl3/datatypes/test/bits_test.py @@ -704,6 +704,12 @@ def test_slice_bits(): with pytest.raises( IndexError ): assert data[x:x] == 0b1 +def test_slice_bits_int(): + data = Bits(8, 0b1101) + assert data[:2] == 0b01 + assert data[2:] == 0b11 + + def test_clone(): a = Bits(4,3) b = a.clone() diff --git a/pymtl3/dsl/test/Slicing_test.py b/pymtl3/dsl/test/Slicing_test.py index fd0318c80..bea186838 100644 --- a/pymtl3/dsl/test/Slicing_test.py +++ b/pymtl3/dsl/test/Slicing_test.py @@ -127,9 +127,7 @@ def up_wr_30_31(): def up_rd_A(): print(s.A[0:17]) - m = Top() - m.elaborate() - simple_sim_pass( m, 0x123 ) + _test_model( Top ) # assert len(m._all_constraints) == 2 # _, x = list(m._all_constraints)[0] @@ -165,6 +163,23 @@ def up_rd_A(): return raise Exception("Should've thrown MultiWriterError.") +# test slicing without specified width +def test_write_two_slices_and_bit_without_specifying_width(): + + class Top( ComponentLevel3 ): + def construct( s ): + s.A = Wire( Bits32 ) + + @update + def up_wr_0_16(): + s.A[:16] @= 0xff + + @update + def up_wr_16_32(): + s.A[16:] @= 0xff + + _test_model(Top) + # write a slice and there are two reader def test_multiple_readers(): From 05d82acf8a5158f836b72aedbcdddde896164551 Mon Sep 17 00:00:00 2001 From: Kelvin Chung Date: Wed, 1 May 2024 10:22:33 +0100 Subject: [PATCH 3/6] update ast helper --- pymtl3/dsl/AstHelper.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/pymtl3/dsl/AstHelper.py b/pymtl3/dsl/AstHelper.py index 1678f2318..1506ad4ad 100644 --- a/pymtl3/dsl/AstHelper.py +++ b/pymtl3/dsl/AstHelper.py @@ -61,8 +61,7 @@ def _get_full_name_up_to_py38( self, input_node ): if x in self.globals: up = (False, x) elif x in self.closure: up = (True, x) - if low is not None and up is not None: - slices.append( slice(low, up) ) + slices.append( slice(low, up) ) # FIXME # else: @@ -160,8 +159,7 @@ def _get_full_name_starting_py39( self, input_node ): if x in self.globals: up = (False, x) elif x in self.closure: up = (True, x) - if low is not None and up is not None: - slices.append( slice(low, up) ) + slices.append( slice(low, up) ) # FIXME # else: From 6b52030996a3073a6a8df2c08f12dc17b87aebaf Mon Sep 17 00:00:00 2001 From: Kelvin Chung Date: Fri, 31 May 2024 19:53:21 +0100 Subject: [PATCH 4/6] fixing verilog import pass --- .../verilog/VerilogPlaceholderConfigs.py | 11 +++++++++ .../verilog/VerilogPlaceholderPass.py | 23 +++++++++++++++++-- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/pymtl3/passes/backends/verilog/VerilogPlaceholderConfigs.py b/pymtl3/passes/backends/verilog/VerilogPlaceholderConfigs.py index 943e26c32..f84cc6577 100644 --- a/pymtl3/passes/backends/verilog/VerilogPlaceholderConfigs.py +++ b/pymtl3/passes/backends/verilog/VerilogPlaceholderConfigs.py @@ -47,6 +47,12 @@ class VerilogPlaceholderConfigs( PlaceholderConfigs ): # The separator used for name mangling "separator" : '__', + + # The name of the clock signal + "clk_name" : "clk", + + # The name of the reset signal + "reset_name" : "rst", } VerilogCheckers = { @@ -65,6 +71,11 @@ class VerilogPlaceholderConfigs( PlaceholderConfigs ): "v_include": Checker( lambda v: isinstance(v, list) and all(os.path.isdir(expand(p)) for p in v), "expects a list of paths to directory"), + + "has_clk": Checker( lambda v: isinstance(v, bool), "expects a bool" ), + "has_reset": Checker( lambda v: isinstance(v, bool), "expects a bool" ), + "clk_name": Checker( lambda v: isinstance(v, str) and v, "expects a non-empty string" ), + "reset_name": Checker( lambda v: isinstance(v, str) and v, "expects a non-empty string" ), } Pass = VerilogPlaceholderPass diff --git a/pymtl3/passes/backends/verilog/VerilogPlaceholderPass.py b/pymtl3/passes/backends/verilog/VerilogPlaceholderPass.py index 818d4d9ca..21e8051dc 100644 --- a/pymtl3/passes/backends/verilog/VerilogPlaceholderPass.py +++ b/pymtl3/passes/backends/verilog/VerilogPlaceholderPass.py @@ -89,6 +89,18 @@ class VerilogPlaceholderPass( PlaceholderPass ): #: Default value: ``'_'`` separator = MetadataKey(str) + #: has clk + has_clk = MetadataKey(bool) + + #: has reset + has_reset = MetadataKey(bool) + + #: clk name + clk_name = MetadataKey(str) + + #: reset name + reset_name = MetadataKey(str) + @staticmethod def get_placeholder_config(): from pymtl3.passes.backends.verilog.VerilogPlaceholderConfigs import ( @@ -338,10 +350,17 @@ def _gen_verilog_wrapper( s, m, cfg, irepr ): ] # Connections between top module and inner module - connect_ports = [ + connect_ports = [] + if s.has_clk: + connect_ports.append(f" .{cfg.clk_name}( clk )," ) + + if s.has_reset: + connect_ports.append(f" .{cfg.reset_name}( reset )," ) + connect_ports.extend([ f" .{name}( {name} ){'' if idx == len(rtlir_ports)-1 else ','}"\ for idx, (_, name, p, _) in enumerate(rtlir_ports) if name - ] + ]) + lines = [ f"module {cfg.pickled_top_module}", From ea0154785747f06bef9dc36dc1d86f12a508ae29 Mon Sep 17 00:00:00 2001 From: cb535 Date: Sat, 17 Aug 2024 12:06:51 -0400 Subject: [PATCH 5/6] Verilator now requires C++14 --- .../backends/verilog/import_/VerilogVerilatorImportConfigs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pymtl3/passes/backends/verilog/import_/VerilogVerilatorImportConfigs.py b/pymtl3/passes/backends/verilog/import_/VerilogVerilatorImportConfigs.py index 5d30baedf..b0e5db15a 100644 --- a/pymtl3/passes/backends/verilog/import_/VerilogVerilatorImportConfigs.py +++ b/pymtl3/passes/backends/verilog/import_/VerilogVerilatorImportConfigs.py @@ -326,7 +326,7 @@ def create_cc_cmd( s ): if not s.is_default("c_flags"): c_flags += f" {expand(s.c_flags)}" - c_flags += f" -fPIC -shared -std=c++11 -pthread" + c_flags += f" -fPIC -shared -std=c++14 -pthread" c_include_path = " ".join("-I"+p for p in s._get_all_includes() if p) out_file = s.get_shared_lib_path() From 1d1792b3bd2a67caa4162f9a402119c36aaaca91 Mon Sep 17 00:00:00 2001 From: Kelvin Chung Date: Fri, 31 May 2024 19:53:21 +0100 Subject: [PATCH 6/6] fixing verilog import pass --- .../verilog/VerilogPlaceholderConfigs.py | 11 +++++++++ .../verilog/VerilogPlaceholderPass.py | 23 +++++++++++++++++-- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/pymtl3/passes/backends/verilog/VerilogPlaceholderConfigs.py b/pymtl3/passes/backends/verilog/VerilogPlaceholderConfigs.py index 943e26c32..f84cc6577 100644 --- a/pymtl3/passes/backends/verilog/VerilogPlaceholderConfigs.py +++ b/pymtl3/passes/backends/verilog/VerilogPlaceholderConfigs.py @@ -47,6 +47,12 @@ class VerilogPlaceholderConfigs( PlaceholderConfigs ): # The separator used for name mangling "separator" : '__', + + # The name of the clock signal + "clk_name" : "clk", + + # The name of the reset signal + "reset_name" : "rst", } VerilogCheckers = { @@ -65,6 +71,11 @@ class VerilogPlaceholderConfigs( PlaceholderConfigs ): "v_include": Checker( lambda v: isinstance(v, list) and all(os.path.isdir(expand(p)) for p in v), "expects a list of paths to directory"), + + "has_clk": Checker( lambda v: isinstance(v, bool), "expects a bool" ), + "has_reset": Checker( lambda v: isinstance(v, bool), "expects a bool" ), + "clk_name": Checker( lambda v: isinstance(v, str) and v, "expects a non-empty string" ), + "reset_name": Checker( lambda v: isinstance(v, str) and v, "expects a non-empty string" ), } Pass = VerilogPlaceholderPass diff --git a/pymtl3/passes/backends/verilog/VerilogPlaceholderPass.py b/pymtl3/passes/backends/verilog/VerilogPlaceholderPass.py index 818d4d9ca..21e8051dc 100644 --- a/pymtl3/passes/backends/verilog/VerilogPlaceholderPass.py +++ b/pymtl3/passes/backends/verilog/VerilogPlaceholderPass.py @@ -89,6 +89,18 @@ class VerilogPlaceholderPass( PlaceholderPass ): #: Default value: ``'_'`` separator = MetadataKey(str) + #: has clk + has_clk = MetadataKey(bool) + + #: has reset + has_reset = MetadataKey(bool) + + #: clk name + clk_name = MetadataKey(str) + + #: reset name + reset_name = MetadataKey(str) + @staticmethod def get_placeholder_config(): from pymtl3.passes.backends.verilog.VerilogPlaceholderConfigs import ( @@ -338,10 +350,17 @@ def _gen_verilog_wrapper( s, m, cfg, irepr ): ] # Connections between top module and inner module - connect_ports = [ + connect_ports = [] + if s.has_clk: + connect_ports.append(f" .{cfg.clk_name}( clk )," ) + + if s.has_reset: + connect_ports.append(f" .{cfg.reset_name}( reset )," ) + connect_ports.extend([ f" .{name}( {name} ){'' if idx == len(rtlir_ports)-1 else ','}"\ for idx, (_, name, p, _) in enumerate(rtlir_ports) if name - ] + ]) + lines = [ f"module {cfg.pickled_top_module}",