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

Cycle Level simulation reset function not right #282

Open
CaseyZhu opened this issue Oct 15, 2024 · 1 comment
Open

Cycle Level simulation reset function not right #282

CaseyZhu opened this issue Oct 15, 2024 · 1 comment

Comments

@CaseyZhu
Copy link

'''
from pymtl3 import *
from pymtl3.stdlib.queues import PipeQueueCL

定义一个简单的被调用组件

class SimpleCallee(Component):
def construct(s):
#s.set = CalleePort(Type=Bits32)
s.send = CallerIfcCL(Type=Bits32)
s.counter = b32(0)
print(s.counter)
#s.set //= s.my_set

    @update_once
    def up_counter_ff():
        if s.send.rdy():
            s.send(s.counter)
            s.counter @= s.counter + b32(1)
    #s.add_constraints(U(up_counter) < U(up_counter_ff))    
    
def line_trace(s):
    return f"Callee: counter={s.counter}"

class SimpleCaller(Component):
def construct(s):
s.receive = CalleeIfcCL(Type=Bits32)
s.received_data = Wire(32)
s.receive //= s.f_receive
'''
s.in_q = PipeQueueCL(num_entries=2)

    s.in_q.enq //= s.receive

    @update_once
    def up_receive():
        if s.in_q.deq.rdy():
            s.received_data @= s.in_q.deq()
    '''
    
@non_blocking( lambda s: True )
def f_receive( s, msg ):
    s.received_data @= msg
    #print(f"Received message: {msg}")
    
def line_trace(s):
    return f"Caller: received={s.received_data}"

class TopLevel(Component):
def construct(s):
s.callee = SimpleCallee()
s.caller = SimpleCaller()
connect(s.callee.send, s.caller.receive)

def line_trace(s):
    return f"{s.callee.line_trace()} -> {s.caller.line_trace()}"

def test_caller_callee():
top = TopLevel()
#top.elaborate()
top.apply(DefaultPassGroup())
#top.sim_reset() 这个会占用仿真时间!!(会触发update_once)
print(top.callee.counter)
print("Starting simulation...")
for i in range(10): # 运行10个周期
top.sim_tick()
print(f"Cycle {i}: {top.line_trace()}")

if name == "main":
test_caller_callee()
'''
the code above will print

00000000
00000000
Starting simulation...
Cycle 0: Callee: counter=00000001 -> Caller: received=00000000
Cycle 1: Callee: counter=00000002 -> Caller: received=00000001
Cycle 2: Callee: counter=00000003 -> Caller: received=00000002
Cycle 3: Callee: counter=00000004 -> Caller: received=00000003
Cycle 4: Callee: counter=00000005 -> Caller: received=00000004
Cycle 5: Callee: counter=00000006 -> Caller: received=00000005
Cycle 6: Callee: counter=00000007 -> Caller: received=00000006
Cycle 7: Callee: counter=00000008 -> Caller: received=00000007
Cycle 8: Callee: counter=00000009 -> Caller: received=00000008
Cycle 9: Callee: counter=0000000a -> Caller: received=00000009

if add sim_reset() the results is wrong
'''
00000000
00000004
Starting simulation...
Cycle 0: Callee: counter=00000005 -> Caller: received=00000004
Cycle 1: Callee: counter=00000006 -> Caller: received=00000005
Cycle 2: Callee: counter=00000007 -> Caller: received=00000006
Cycle 3: Callee: counter=00000008 -> Caller: received=00000007
Cycle 4: Callee: counter=00000009 -> Caller: received=00000008
Cycle 5: Callee: counter=0000000a -> Caller: received=00000009
Cycle 6: Callee: counter=0000000b -> Caller: received=0000000a
Cycle 7: Callee: counter=0000000c -> Caller: received=0000000b
Cycle 8: Callee: counter=0000000d -> Caller: received=0000000c
Cycle 9: Callee: counter=0000000e -> Caller: received=0000000d
'''

@yo96
Copy link
Contributor

yo96 commented Oct 16, 2024

Hi,

Thank you for using PyMTL3. The issue is that when you call the sim_reset() method, the clock will be advanced, and the first few messages will be transmitted. If you are doing pure CL simulation, sim_reset() is not needed since all it does is just toggling the reset signal and ticking the clock for a few cycles.

If you do want to use the reset signal for some reason, you can either write your own reset function to do what you want or modify your update block to not do anything during reset, for example:

    @update_once
    def up_counter_ff():
        if s.reset:
            s.counter @= 0
        elif s.send.rdy():
            s.send(s.counter)
            s.counter @= s.counter + b32(1)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants