Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Port the bitstruct packed array bug fix to master branch #249

Merged
merged 7 commits into from
Nov 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion .github/workflows/python-package-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,15 @@ on:

jobs:
build:
runs-on: ubuntu-latest
# The latest ubuntu release may exclude Python versions that have reached
# the end of life. An example of this is the upgrade from ubuntu-20.04 to
# ubuntu-22.04: support for Python 3.6.* and 3.7.* has been dropped and
# this broke our Github actions. We should periodically revisit this to
# make sure PyMTL works on the latest ubuntu LTS release. As of now I'm
# targeting ubuntu-20.04 because lots of PyMTL users still work with
# Python 3.6 and 3.7.
# runs-on: ubuntu-latest
runs-on: ubuntu-20.04
strategy:
fail-fast: false
matrix:
Expand Down
29 changes: 25 additions & 4 deletions pymtl3/dsl/Connectable.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,10 +213,31 @@
xd.top_level_signal = sd.top_level_signal
xd.elaborate_top = sd.elaborate_top

xd.my_name = name + "".join([ f"[{y}]" for y in indices ])
xd.full_name = f"{sd.full_name}.{name}"
xd._my_name = name
xd._my_indices = indices
# @bitstruct
# class SomeMsg:
# a: [ Bits8, Bits8 ]
# b: Bits32
# ...
# class A ( Component ):
# def construct( s ):
# s.struct_port = InPort( SomeMsg )
#
# Then, the newly created ports representing field a should be
# suffixed with the index, i.e., the name should be
# s.struct_port.a[0], s.struct_port.a[1]. Without the if
# statement below, both ports would have the same name
# s.struct_port.a, which can cause errors in simulation.
if is_bitstruct_class(s._dsl.Type):
xd.my_name = name + "".join([ f"[{y}]" for y in indices ])
xd.full_name = f"{sd.full_name}.{name}"+"".join([ f"[{y}]" for y in indices ])
xd._my_name = name
xd._my_indices = indices

else:
xd.my_name = name + "".join([ f"[{y}]" for y in indices ])
xd.full_name = f"{sd.full_name}.{name}"
xd._my_name = name
xd._my_indices = indices

Check warning on line 240 in pymtl3/dsl/Connectable.py

View check run for this annotation

Codecov / codecov/patch

pymtl3/dsl/Connectable.py#L237-L240

Added lines #L237 - L240 were not covered by tests

if parent_is_list:
parent.append( x )
Expand Down
140 changes: 139 additions & 1 deletion pymtl3/passes/sim/test/DynamicSchedulePass_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ def _test_model( cls ):
A.apply( GenDAGPass() )
A.apply( DynamicSchedulePass() )
A.apply( PrepareSimPass() )

A.sim_reset()
A.sim_eval_combinational()

Expand Down Expand Up @@ -259,6 +258,145 @@ def construct( s ):
return
raise Exception("Should've thrown AssertionError")

def test_struct_with_list_field():

@bitstruct
class SomeMsg:
a: [ Bits8, Bits8 ]
b: [ Bits32, Bits32 ]

class Top( Component ):
def construct( s ):
s.struct = Wire(SomeMsg)
s.a = Wire(32)
s.b = Wire(32)

@update
def up_out():
s.struct.a[0] @= 0
s.struct.a[1] @= 1
s.struct.b[0] @= 2
s.struct.b[1] @= 3
s.b @= s.a + 1

@update
def up_abcd():
s.a @= s.struct.b[1] + 1

dut = Top()
dut.elaborate()
dut.apply( GenDAGPass() )
dut.apply( DynamicSchedulePass() )
dut.apply( PrepareSimPass(print_line_trace=False) )
dut.sim_reset()
dut.sim_tick()
assert dut.a == 4
assert dut.b == 5

def test_struct_with_nested_list_field():
@bitstruct
class SomeMsgA:
a: [ Bits8, Bits8 ]
b: [ Bits32, Bits32 ]

@bitstruct
class SomeMsgB:
msg_a: [ SomeMsgA, SomeMsgA ]
b: [ Bits32, Bits32 ]

class Top( Component ):
def construct( s ):
s.struct = Wire(SomeMsgB)
s.a = Wire(32)
s.b = Wire(32)

@update
def up_out():
s.struct.msg_a[0].a[0] @= 1
s.struct.msg_a[0].a[1] @= 2
s.struct.msg_a[0].b[0] @= 3
s.struct.msg_a[0].b[1] @= 4

s.struct.msg_a[1].a[0] @= 5
s.struct.msg_a[1].a[1] @= 6
s.struct.msg_a[1].b[0] @= 7
s.struct.msg_a[1].b[1] @= 8

s.struct.b[0] @= 9
s.struct.b[1] @= 10
s.b @= s.a + 1

@update
def up_abcd():
s.a @= s.struct.msg_a[1].b[1] + 1

dut = Top()
dut.elaborate()
dut.apply( GenDAGPass() )
dut.apply( DynamicSchedulePass() )
dut.apply( PrepareSimPass(print_line_trace=False) )
dut.sim_reset()
dut.sim_tick()
assert dut.a == 9
assert dut.b == 10

def test_list_struct_port_with_nested_list_field():
@bitstruct
class SomeMsgA:
a: [ Bits8, Bits8 ]
b: [ Bits32, Bits32 ]

@bitstruct
class SomeMsgB:
msg_a: [ SomeMsgA, SomeMsgA ]
b: [ Bits32, Bits32 ]

class Top( Component ):
def construct( s ):
s.struct = [ Wire(SomeMsgB) for _ in range(2) ]
s.a = Wire(32)
s.b = Wire(32)

@update
def up_out():
s.struct[0].msg_a[0].a[0] @= 1
s.struct[0].msg_a[0].a[1] @= 2
s.struct[0].msg_a[0].b[0] @= 3
s.struct[0].msg_a[0].b[1] @= 4
s.struct[0].msg_a[1].a[0] @= 5
s.struct[0].msg_a[1].a[1] @= 6
s.struct[0].msg_a[1].b[0] @= 7
s.struct[0].msg_a[1].b[1] @= 8
s.struct[0].b[0] @= 9
s.struct[0].b[1] @= 10

s.struct[1].msg_a[0].a[0] @= 11
s.struct[1].msg_a[0].a[1] @= 12
s.struct[1].msg_a[0].b[0] @= 13
s.struct[1].msg_a[0].b[1] @= 14
s.struct[1].msg_a[1].a[0] @= 15
s.struct[1].msg_a[1].a[1] @= 16
s.struct[1].msg_a[1].b[0] @= 17
s.struct[1].msg_a[1].b[1] @= 18
s.struct[1].b[0] @= 19
s.struct[1].b[1] @= 20

s.b @= s.a + 1

@update
def up_abcd():
s.a @= s.struct[0].msg_a[1].b[1] + s.struct[1].msg_a[0].b[0]

dut = Top()
dut.elaborate()
dut.apply( GenDAGPass() )
dut.apply( DynamicSchedulePass() )
dut.apply( PrepareSimPass(print_line_trace=False) )
dut.sim_reset()
dut.sim_tick()
assert dut.a == 21
assert dut.b == 22

def test_equal_top_level():
class A(Component):
def construct( s ):
Expand Down
2 changes: 1 addition & 1 deletion pymtl3/version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "3.1.14"
__version__ = "3.1.15"

Check warning on line 1 in pymtl3/version.py

View check run for this annotation

Codecov / codecov/patch

pymtl3/version.py#L1

Added line #L1 was not covered by tests
Loading