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

Make simulation instances standalone (or... multiple simulation instances). #68

Closed
hgomersall opened this Issue May 1, 2015 · 36 comments

Comments

Projects
None yet
7 participants
@hgomersall
Contributor

hgomersall commented May 1, 2015

An issue that keeps coming up in various guises, and is the root cause of this PR, is the problem of global state in simulation instances.

It has been suggested that it is desirable to have multiple simulation instances. Personally I am fairly agnostic on this specific issue, but the removal of global state would allow this.

This issue is to discuss the problem of global state in simulation and collect opinion.

@jpcaram

This comment has been minimized.

Show comment
Hide comment
@jpcaram

jpcaram May 2, 2015

Here is my experience/opinion:

  1. Globals are problematic (Common notion and personal opinion).
  2. The use of the interactive interpreter (iPython is popular in the scientific community) leads to the multiple-instance problem. One wants to be able to run more than one simulation without exiting the interpreter.
  3. Using MyHDL as part of a bigger program (e.g. a mixed-signal simulator or GUI) does too. The parent program might require invoking simulations simultaneously or sequentially without exiting. A workaround is launching simulations in separate processes.

jpcaram commented May 2, 2015

Here is my experience/opinion:

  1. Globals are problematic (Common notion and personal opinion).
  2. The use of the interactive interpreter (iPython is popular in the scientific community) leads to the multiple-instance problem. One wants to be able to run more than one simulation without exiting the interpreter.
  3. Using MyHDL as part of a bigger program (e.g. a mixed-signal simulator or GUI) does too. The parent program might require invoking simulations simultaneously or sequentially without exiting. A workaround is launching simulations in separate processes.
@jandecaluwe

This comment has been minimized.

Show comment
Hide comment
@jandecaluwe

jandecaluwe May 3, 2015

Contributor

I find this a rather theoretical discussion.
I am fully aware of the limitations imposed by globals. What I do not see is an HDL API that does not rely on them to some extent and that users will find acceptable. I have the impression people don't understand the practical implications of such a design. Ready to be proven wrong of course.

Contributor

jandecaluwe commented May 3, 2015

I find this a rather theoretical discussion.
I am fully aware of the limitations imposed by globals. What I do not see is an HDL API that does not rely on them to some extent and that users will find acceptable. I have the impression people don't understand the practical implications of such a design. Ready to be proven wrong of course.

@jmgc

This comment has been minimized.

Show comment
Hide comment
@jmgc

jmgc May 3, 2015

Contributor

Dear Jan,

Not trying to prove you wrong, just sharing thoughts ;)

First, sorry if what I say has been mentioned before.

As far as I understand, the reason to use globals is because Signals and Waiters, at least, need to share a common place to get information.

I have found two possible alternatives:

The first would be to create a register of running simulations identified (for example) using the id of the Simulation instance. Then look for all the signals in the present generator and modify every one of this signals adding an attribute with the reference to the simulator instance (for example). This will allow every signal to find its information of its _simulator. I understand that a procedure based on visitors (similar to the one used in conversion) could be used, but the amount of work can be quite large. In any case it should be feasible, and no major changes are needed.

Second option would use the same register, and provide a way to the signals to find its calling Simulation instance id. For this, a change in Simulation would be needed: Instead of requiring a list of generators already called, just request a list of names of generators, like in verify (for example). Inside the Simulation.init the Simulation instance must register itself. Then, call the different generators. Every Signal and Waiter will be able to find the id of the Simulation just looking in every tuple element of the list provided by inspect.stack when the _Signal.init function is called. The element 0 of the tuple will have a string, and it should indicate that frame which should be init inside _Simulation.py, and there you will find the id of the Simulation also. Then you just have to look inside the Simulations register with this id to find the information needed. If Signals are provided as arguments to the generator (I am not sure if this makes sense), this Signals can have an attribute which can allow to add this Simulation identifier.

Probably, there would be some simpler alternatives that will work also, but these are the most promising I have found.

Best,

    Jose M.

El 3/5/2015, a las 19:23, jandecaluwe notifications@github.com escribió:

I find this a rather theoretical discussion.
I am fully aware of the limitations imposed by globals. What I do not see is an HDL API that does not rely on them to some extent and that users will find acceptable. I have the impression people don't understand the practical implications of such a design. Ready to be proven wrong of course.


Reply to this email directly or view it on GitHub #68 (comment).

Contributor

jmgc commented May 3, 2015

Dear Jan,

Not trying to prove you wrong, just sharing thoughts ;)

First, sorry if what I say has been mentioned before.

As far as I understand, the reason to use globals is because Signals and Waiters, at least, need to share a common place to get information.

I have found two possible alternatives:

The first would be to create a register of running simulations identified (for example) using the id of the Simulation instance. Then look for all the signals in the present generator and modify every one of this signals adding an attribute with the reference to the simulator instance (for example). This will allow every signal to find its information of its _simulator. I understand that a procedure based on visitors (similar to the one used in conversion) could be used, but the amount of work can be quite large. In any case it should be feasible, and no major changes are needed.

Second option would use the same register, and provide a way to the signals to find its calling Simulation instance id. For this, a change in Simulation would be needed: Instead of requiring a list of generators already called, just request a list of names of generators, like in verify (for example). Inside the Simulation.init the Simulation instance must register itself. Then, call the different generators. Every Signal and Waiter will be able to find the id of the Simulation just looking in every tuple element of the list provided by inspect.stack when the _Signal.init function is called. The element 0 of the tuple will have a string, and it should indicate that frame which should be init inside _Simulation.py, and there you will find the id of the Simulation also. Then you just have to look inside the Simulations register with this id to find the information needed. If Signals are provided as arguments to the generator (I am not sure if this makes sense), this Signals can have an attribute which can allow to add this Simulation identifier.

Probably, there would be some simpler alternatives that will work also, but these are the most promising I have found.

Best,

    Jose M.

El 3/5/2015, a las 19:23, jandecaluwe notifications@github.com escribió:

I find this a rather theoretical discussion.
I am fully aware of the limitations imposed by globals. What I do not see is an HDL API that does not rely on them to some extent and that users will find acceptable. I have the impression people don't understand the practical implications of such a design. Ready to be proven wrong of course.


Reply to this email directly or view it on GitHub #68 (comment).

@jandecaluwe

This comment has been minimized.

Show comment
Hide comment
@jandecaluwe

jandecaluwe May 3, 2015

Contributor

Please don't worry about proving me wrong, nothing wrong with that.

I don't see how your proposals gets rid of globals, which I understand is the intention. You seem to add a global registry, and a lot of machinery to attach globally known signals to the right simulator. Seems all very complicated and I fear for performance with all those (dynamic?) look-ups.

Remember, the setup to beat is simply using multiple processes - something you can do right now with no change.

Contributor

jandecaluwe commented May 3, 2015

Please don't worry about proving me wrong, nothing wrong with that.

I don't see how your proposals gets rid of globals, which I understand is the intention. You seem to add a global registry, and a lot of machinery to attach globally known signals to the right simulator. Seems all very complicated and I fear for performance with all those (dynamic?) look-ups.

Remember, the setup to beat is simply using multiple processes - something you can do right now with no change.

@jmgc

This comment has been minimized.

Show comment
Hide comment
@jmgc

jmgc May 3, 2015

Contributor

In principle, only the register will be global. It could be just a dictionary containing a key which would be the id of the Simulator, and an object, which will be based on a class with the same attributes as the _simulator file globals, lets call it _simulator_class.

In the first case, it is done just once, when the Simulation instance is created, and stores the _simulator_class as an attribute inside the Signal or Waiter, for example self._simulator. Then, all the different functions that presently call the _simulator file variables in the present design, just have to call to the _simulator_class attributes.

In the second case, it is done when every Signal is created (just once). It searchs for its Simulation object id, and based on it, looks for the _simulator object in the register and stores its reference also as self._simulator

I do not know if it will affect much to the performance, but calling an attribute of an object should not be much worse than calling a global. If this is the case, then we just can store the reference for every attribute of the __simulator_class inside every Signal and Waiter.

Sincerely, presently I am not using multiple Simulations, but I have been thinking about this problem just in case I need it in a future.

Best,

    Jose M.

El 3/5/2015, a las 21:49, jandecaluwe notifications@github.com escribió:

Please don't worry about proving me wrong, nothing wrong with that.

I don't see how your proposals get rid of globals, which I understand is the intention. You seem to add a global registry, and a lot of machinery to attach globally known signals to the right simulator. Seems all very complicated and I fear for performance with all this (dynamic?) look-ups.

Remember, the setup to beat is simply using multiple processes - something you can do right now with no change.


Reply to this email directly or view it on GitHub #68 (comment).

Contributor

jmgc commented May 3, 2015

In principle, only the register will be global. It could be just a dictionary containing a key which would be the id of the Simulator, and an object, which will be based on a class with the same attributes as the _simulator file globals, lets call it _simulator_class.

In the first case, it is done just once, when the Simulation instance is created, and stores the _simulator_class as an attribute inside the Signal or Waiter, for example self._simulator. Then, all the different functions that presently call the _simulator file variables in the present design, just have to call to the _simulator_class attributes.

In the second case, it is done when every Signal is created (just once). It searchs for its Simulation object id, and based on it, looks for the _simulator object in the register and stores its reference also as self._simulator

I do not know if it will affect much to the performance, but calling an attribute of an object should not be much worse than calling a global. If this is the case, then we just can store the reference for every attribute of the __simulator_class inside every Signal and Waiter.

Sincerely, presently I am not using multiple Simulations, but I have been thinking about this problem just in case I need it in a future.

Best,

    Jose M.

El 3/5/2015, a las 21:49, jandecaluwe notifications@github.com escribió:

Please don't worry about proving me wrong, nothing wrong with that.

I don't see how your proposals get rid of globals, which I understand is the intention. You seem to add a global registry, and a lot of machinery to attach globally known signals to the right simulator. Seems all very complicated and I fear for performance with all this (dynamic?) look-ups.

Remember, the setup to beat is simply using multiple processes - something you can do right now with no change.


Reply to this email directly or view it on GitHub #68 (comment).

@jandecaluwe

This comment has been minimized.

Show comment
Hide comment
@jandecaluwe

jandecaluwe May 3, 2015

Contributor

If only the register is global, then Signals are local. That means they are stored on their Simulation instance, and nowhere else. I don't see how you can do that unless you return them together with instances (!!) or give them a simulation instance argument (!!). Not very attractive.

Contributor

jandecaluwe commented May 3, 2015

If only the register is global, then Signals are local. That means they are stored on their Simulation instance, and nowhere else. I don't see how you can do that unless you return them together with instances (!!) or give them a simulation instance argument (!!). Not very attractive.

@jmgc

This comment has been minimized.

Show comment
Hide comment
@jmgc

jmgc May 3, 2015

Contributor

I am not explaining myself. Let’s assume that we have a register that it is a dictionary. I store in this dictionary an id as key and an object as value. This object has all the information that is stored nowadays in the _simulator file variables as attributes.

As it is an object that is shared among all the Signals and the register, the access will be similar to global, because everybody can access to it, you just only need the id of the Simulator running the code to have access to the information.

So you can have multiple instances of the simulator, and at the same time, they behave in a similar fashion as the present solution.

Of course, there could be aspects that I do not foresee.

Do you think it would be possible to modify a little the Simulation class to allow the creation of the Signals inside the init function? If this is possible, a quick check can be done to see how things behave.

Best,

    Jose M.

El 3/5/2015, a las 22:45, jandecaluwe notifications@github.com escribió:

If only the register is global, then Signals are local. That means they are stored on their Simulation instance, and nowhere else. I don't see how you can do that unless you return them together with instances (!!) or give them a simulation instance argument (!!). Not very attractive.


Reply to this email directly or view it on GitHub #68 (comment).

Contributor

jmgc commented May 3, 2015

I am not explaining myself. Let’s assume that we have a register that it is a dictionary. I store in this dictionary an id as key and an object as value. This object has all the information that is stored nowadays in the _simulator file variables as attributes.

As it is an object that is shared among all the Signals and the register, the access will be similar to global, because everybody can access to it, you just only need the id of the Simulator running the code to have access to the information.

So you can have multiple instances of the simulator, and at the same time, they behave in a similar fashion as the present solution.

Of course, there could be aspects that I do not foresee.

Do you think it would be possible to modify a little the Simulation class to allow the creation of the Signals inside the init function? If this is possible, a quick check can be done to see how things behave.

Best,

    Jose M.

El 3/5/2015, a las 22:45, jandecaluwe notifications@github.com escribió:

If only the register is global, then Signals are local. That means they are stored on their Simulation instance, and nowhere else. I don't see how you can do that unless you return them together with instances (!!) or give them a simulation instance argument (!!). Not very attractive.


Reply to this email directly or view it on GitHub #68 (comment).

@jpcaram

This comment has been minimized.

Show comment
Hide comment
@jpcaram

jpcaram May 4, 2015

I understand that the simple syntax of MyHDL is an important asset. This simple syntax is made possible by the use of introspection and global variables, which come at a cost.

One example is the now() function. If it was a member of the Simulation() instance, we would need to pass the reference to each logic module and this would take away from the cleanliness of the syntax.

I.e.

@always(clk.posedge)
def my_logic():
   print "It's", now()

But I don't think this is the only way. I don't have an answer ready at the moment, but I suspect that Python's introspection tools can be leveraged again to create local references for each simulation instance.

Perhaps Jan could provide a basic code snippet illustrating the problem and we could try to solve the specific case without sacrificing syntax and speed?

Thanks!

jpcaram commented May 4, 2015

I understand that the simple syntax of MyHDL is an important asset. This simple syntax is made possible by the use of introspection and global variables, which come at a cost.

One example is the now() function. If it was a member of the Simulation() instance, we would need to pass the reference to each logic module and this would take away from the cleanliness of the syntax.

I.e.

@always(clk.posedge)
def my_logic():
   print "It's", now()

But I don't think this is the only way. I don't have an answer ready at the moment, but I suspect that Python's introspection tools can be leveraged again to create local references for each simulation instance.

Perhaps Jan could provide a basic code snippet illustrating the problem and we could try to solve the specific case without sacrificing syntax and speed?

Thanks!

@jmgc

This comment has been minimized.

Show comment
Hide comment
@jmgc

jmgc May 4, 2015

Contributor

Yes, this is one case, and also traceSignals will require some analysis.

Best,

    Jose M.

El 4/5/2015, a las 15:47, jpcaram notifications@github.com escribió:

I understand that the simple syntax of MyHDL is an important asset. This simple syntax is made possible by the use of introspection and global variables, which come at a cost.

One example is the now() function. If it was a member of the Simulation() instance, we would need to pass the reference to each logic module and this would take away from the cleanliness of the syntax.

I.e.

@Always(clk.posedge)
def my_logic():
print "It's", now()
But I don't think this is the only way. I don't have an answer ready at the moment, but I suspect that Python's introspection tools can be leveraged again to create local references for each simulation instance.

Perhaps Jan could provide a basic code snippet illustrating the problem and we could try to solve the specific case without sacrificing syntax and speed?

Thanks!


Reply to this email directly or view it on GitHub #68 (comment).

Contributor

jmgc commented May 4, 2015

Yes, this is one case, and also traceSignals will require some analysis.

Best,

    Jose M.

El 4/5/2015, a las 15:47, jpcaram notifications@github.com escribió:

I understand that the simple syntax of MyHDL is an important asset. This simple syntax is made possible by the use of introspection and global variables, which come at a cost.

One example is the now() function. If it was a member of the Simulation() instance, we would need to pass the reference to each logic module and this would take away from the cleanliness of the syntax.

I.e.

@Always(clk.posedge)
def my_logic():
print "It's", now()
But I don't think this is the only way. I don't have an answer ready at the moment, but I suspect that Python's introspection tools can be leveraged again to create local references for each simulation instance.

Perhaps Jan could provide a basic code snippet illustrating the problem and we could try to solve the specific case without sacrificing syntax and speed?

Thanks!


Reply to this email directly or view it on GitHub #68 (comment).

@cfelton

This comment has been minimized.

Show comment
Hide comment
@cfelton

cfelton May 4, 2015

Member

At this point, I am not a fan of the multiple simulation instances. The examples that have been given so far as justification for multiple instances have other solutions.

My reasons are the same as those eluded: the complexity required. What are the policies? Can multiple instance communicate to each other? Do they communicate via the existing Signals? Can the Signals have multiple drivers in each sim instance? Can a generators exist in each instance? If not how is it enforced? If so, how are contentions resolved? Etc. etc.

Member

cfelton commented May 4, 2015

At this point, I am not a fan of the multiple simulation instances. The examples that have been given so far as justification for multiple instances have other solutions.

My reasons are the same as those eluded: the complexity required. What are the policies? Can multiple instance communicate to each other? Do they communicate via the existing Signals? Can the Signals have multiple drivers in each sim instance? Can a generators exist in each instance? If not how is it enforced? If so, how are contentions resolved? Etc. etc.

@hgomersall

This comment has been minimized.

Show comment
Hide comment
@hgomersall

hgomersall May 4, 2015

Contributor

I'm pretty relaxed as regards multiple instances or not. However, I'm very keen to see global state removed, which would enable multiple instances. My issues last week came down entirely to global state issues not being caught properly.

Contributor

hgomersall commented May 4, 2015

I'm pretty relaxed as regards multiple instances or not. However, I'm very keen to see global state removed, which would enable multiple instances. My issues last week came down entirely to global state issues not being caught properly.

@jpcaram

This comment has been minimized.

Show comment
Hide comment
@jpcaram

jpcaram May 4, 2015

What about something like this...

# End-user function
def myfunc():
   now()

# Library code
def now():
   print "Hello globals!"

class Sim():
   def __init__(some_func):
      self.func = some_func
      self.patch(some_func)

   def now(self):
      print "Hello locals!"

   def patch(self):
      # Here we do something like in
      # http://www.jonathon-vogel.com/posts/patching_function_bytecode_with_python/

We can locate the calls to the global now() when instantiating s = Sim(myfunc) and replace it with the local self.now(). Okay, might sound nasty, don't hate me, but the outcome is: 1) Same clean syntax for the end-user, 2) No look-ups, therefore maximum speed, and 3) No globals! At least it is possible.

jpcaram commented May 4, 2015

What about something like this...

# End-user function
def myfunc():
   now()

# Library code
def now():
   print "Hello globals!"

class Sim():
   def __init__(some_func):
      self.func = some_func
      self.patch(some_func)

   def now(self):
      print "Hello locals!"

   def patch(self):
      # Here we do something like in
      # http://www.jonathon-vogel.com/posts/patching_function_bytecode_with_python/

We can locate the calls to the global now() when instantiating s = Sim(myfunc) and replace it with the local self.now(). Okay, might sound nasty, don't hate me, but the outcome is: 1) Same clean syntax for the end-user, 2) No look-ups, therefore maximum speed, and 3) No globals! At least it is possible.

@cfelton

This comment has been minimized.

Show comment
Hide comment
@cfelton

cfelton May 4, 2015

Member

I think this thread is lacking focus and I doubt I will be able to bring any :) @heng, I believe a reasonable argument can be made that the issue you ran into was not the simulators global state but your global state that was not handled. We use the simulator to control the state of the module under simulation (MUS, couldn't resist) [1] .

An example where the design does not use global state:

def test():
    x = Signal(0)
    y = Signal(0)

    @always(delay(4))
    def inc():
        x.next = x + 1

    @always_comb
    def compare():
        if x > 8:
            y.next = True
        print("@ {} x is greater than 8".format(now()))
        else:
            y.next = False

    return inc, compare

The Signals above are local to test and are actually kinda hard to access (even though Python provides limited protection).

If we run the above module and only _SuspendSimulation:

sim = Simulation(test())
sim.run(50)
sim.run(50)

and then

sim = Simulation(test())
sim.run(50)
sim.run(50)

Everything works [2] but if you run the gist example it fails because the design uses globals! In the gist example, it is not because the simulator uses globals, it is because the example uses globals. The simulator needs to maintain the state it is controlling, in the above example that is the state in test and in gist example it is the state in the confused_sim.py Python module.

The issue was the expectation that the simulator would take care of your global state (maybe a reasonable assumption?).

The other global state that @jmgc and @jpcaram are referring to is the required global state to make sure only one simulator is running at a time. Simply removing this global state will not make the simulator multiple instances. Personally, I think we are trying to force C like guidelines into this conversation. Also, I don't know if we are successfully discerning global state and global variable.

I think for this thread to make progress it has to focus on: if multiple simulations instances make sense and how are the issues that have been brought going to be solved?

[1] The myhdl simulator is more flexible than other simulators in
that you can give it a collection of generators and not just
a top-level module. This special case is the example that forced
the issue in PR #67.

[2] Output from the above simulation

>> python issue68.py 
@ 36 x is greater than 8
@ 40 x is greater than 8
@ 44 x is greater than 8
@ 48 x is greater than 8
<class 'myhdl._SuspendSimulation'>: Simulated 50 timesteps
@ 52 x is greater than 8
@ 56 x is greater than 8
@ 60 x is greater than 8
@ 64 x is greater than 8
@ 68 x is greater than 8
@ 72 x is greater than 8
@ 76 x is greater than 8
@ 80 x is greater than 8
@ 84 x is greater than 8
@ 88 x is greater than 8
@ 92 x is greater than 8
@ 96 x is greater than 8
@ 100 x is greater than 8
<class 'myhdl._SuspendSimulation'>: Simulated 50 timesteps
@ 36 x is greater than 8
@ 40 x is greater than 8
@ 44 x is greater than 8
@ 48 x is greater than 8
<class 'myhdl._SuspendSimulation'>: Simulated 50 timesteps
@ 52 x is greater than 8
@ 56 x is greater than 8
@ 60 x is greater than 8
@ 64 x is greater than 8
@ 68 x is greater than 8
@ 72 x is greater than 8
@ 76 x is greater than 8
@ 80 x is greater than 8
@ 84 x is greater than 8
@ 88 x is greater than 8
@ 92 x is greater than 8
@ 96 x is greater than 8
@ 100 x is greater than 8
<class 'myhdl._SuspendSimulation'>: Simulated 50 timesteps
Member

cfelton commented May 4, 2015

I think this thread is lacking focus and I doubt I will be able to bring any :) @heng, I believe a reasonable argument can be made that the issue you ran into was not the simulators global state but your global state that was not handled. We use the simulator to control the state of the module under simulation (MUS, couldn't resist) [1] .

An example where the design does not use global state:

def test():
    x = Signal(0)
    y = Signal(0)

    @always(delay(4))
    def inc():
        x.next = x + 1

    @always_comb
    def compare():
        if x > 8:
            y.next = True
        print("@ {} x is greater than 8".format(now()))
        else:
            y.next = False

    return inc, compare

The Signals above are local to test and are actually kinda hard to access (even though Python provides limited protection).

If we run the above module and only _SuspendSimulation:

sim = Simulation(test())
sim.run(50)
sim.run(50)

and then

sim = Simulation(test())
sim.run(50)
sim.run(50)

Everything works [2] but if you run the gist example it fails because the design uses globals! In the gist example, it is not because the simulator uses globals, it is because the example uses globals. The simulator needs to maintain the state it is controlling, in the above example that is the state in test and in gist example it is the state in the confused_sim.py Python module.

The issue was the expectation that the simulator would take care of your global state (maybe a reasonable assumption?).

The other global state that @jmgc and @jpcaram are referring to is the required global state to make sure only one simulator is running at a time. Simply removing this global state will not make the simulator multiple instances. Personally, I think we are trying to force C like guidelines into this conversation. Also, I don't know if we are successfully discerning global state and global variable.

I think for this thread to make progress it has to focus on: if multiple simulations instances make sense and how are the issues that have been brought going to be solved?

[1] The myhdl simulator is more flexible than other simulators in
that you can give it a collection of generators and not just
a top-level module. This special case is the example that forced
the issue in PR #67.

[2] Output from the above simulation

>> python issue68.py 
@ 36 x is greater than 8
@ 40 x is greater than 8
@ 44 x is greater than 8
@ 48 x is greater than 8
<class 'myhdl._SuspendSimulation'>: Simulated 50 timesteps
@ 52 x is greater than 8
@ 56 x is greater than 8
@ 60 x is greater than 8
@ 64 x is greater than 8
@ 68 x is greater than 8
@ 72 x is greater than 8
@ 76 x is greater than 8
@ 80 x is greater than 8
@ 84 x is greater than 8
@ 88 x is greater than 8
@ 92 x is greater than 8
@ 96 x is greater than 8
@ 100 x is greater than 8
<class 'myhdl._SuspendSimulation'>: Simulated 50 timesteps
@ 36 x is greater than 8
@ 40 x is greater than 8
@ 44 x is greater than 8
@ 48 x is greater than 8
<class 'myhdl._SuspendSimulation'>: Simulated 50 timesteps
@ 52 x is greater than 8
@ 56 x is greater than 8
@ 60 x is greater than 8
@ 64 x is greater than 8
@ 68 x is greater than 8
@ 72 x is greater than 8
@ 76 x is greater than 8
@ 80 x is greater than 8
@ 84 x is greater than 8
@ 88 x is greater than 8
@ 92 x is greater than 8
@ 96 x is greater than 8
@ 100 x is greater than 8
<class 'myhdl._SuspendSimulation'>: Simulated 50 timesteps
@jmgc

This comment has been minimized.

Show comment
Hide comment
@jmgc

jmgc May 5, 2015

Contributor

@cfelton, let me try to bring another perspective. I am trying to simulate a large device with a complex architecture. It takes hours to be simulated on a VHDL simulator like vsim. Probably, if it could be parallelized it would work faster. I cannot modify vsim, but I can do it with mydhl. So I was planning to divide the device in modules, and interchange information among them. This way I could run multiple instances, one for every module, and parallelise the simulation. Presently, this is not possible because the state is unique and global for all the possible instances. But with these changes, why not?

Of course, there could alternatives with Myhdl that I am not aware of. If this is the case, I am eager to learn.

Contributor

jmgc commented May 5, 2015

@cfelton, let me try to bring another perspective. I am trying to simulate a large device with a complex architecture. It takes hours to be simulated on a VHDL simulator like vsim. Probably, if it could be parallelized it would work faster. I cannot modify vsim, but I can do it with mydhl. So I was planning to divide the device in modules, and interchange information among them. This way I could run multiple instances, one for every module, and parallelise the simulation. Presently, this is not possible because the state is unique and global for all the possible instances. But with these changes, why not?

Of course, there could alternatives with Myhdl that I am not aware of. If this is the case, I am eager to learn.

@jpcaram

This comment has been minimized.

Show comment
Hide comment
@jpcaram

jpcaram May 5, 2015

I believe the globals (shared by instances of Simulation, the now function, and others) that we are talking about are, at least:

_simulator._signals
_simulator._siglist
_simulator._futureEvents
_simulator.time
_simulator._cosim
_simulator._tracing
_simulator._tf

_traceSignals._tracing
_traceSignals._profileFunc

@cfelton , why do you say "required global state to make sure only one simulator is running at a time". I don't think global states are a requirement and that a having a single simulator at a time has to be ensured.

I believe the question is, can we move all/most of these variables inside the classes' instances, and still make sure the end-user still keeps the nice and simple interface, and that we do not compromise performance? Just to start putting some structure to the discussion, do we agree on this?

@jmgc , you can do the parallelizing by launching separate Simulation(...).run() in different processes. I've done it. It won't work with threads because of the globals. Of course, threads or processes will require quite some overhead in your coding.

jpcaram commented May 5, 2015

I believe the globals (shared by instances of Simulation, the now function, and others) that we are talking about are, at least:

_simulator._signals
_simulator._siglist
_simulator._futureEvents
_simulator.time
_simulator._cosim
_simulator._tracing
_simulator._tf

_traceSignals._tracing
_traceSignals._profileFunc

@cfelton , why do you say "required global state to make sure only one simulator is running at a time". I don't think global states are a requirement and that a having a single simulator at a time has to be ensured.

I believe the question is, can we move all/most of these variables inside the classes' instances, and still make sure the end-user still keeps the nice and simple interface, and that we do not compromise performance? Just to start putting some structure to the discussion, do we agree on this?

@jmgc , you can do the parallelizing by launching separate Simulation(...).run() in different processes. I've done it. It won't work with threads because of the globals. Of course, threads or processes will require quite some overhead in your coding.

@jandecaluwe

This comment has been minimized.

Show comment
Hide comment
@jandecaluwe

jandecaluwe May 5, 2015

Contributor
from multiprocessing import Pool
from myhdl import *

def t(n):
    @instance
    def p():
        for i in range(4):
            yield delay(10)
            print n, now()
    return p

def s(n):
    Simulation(t(n)).run()

p = Pool(4)
p.map(s, (1, 2, 3, 4))
3 10
4 10
3 20
4 20
3 30
4 30
3 40
4 40
<class 'myhdl.StopSimulation'>: No more events<class 'myhdl.StopSimulation'>: No more events

1 10
2 10
2 20
1 20
2 30
1 30
2 40
1 40
<class 'myhdl.StopSimulation'>: No more events<class 'myhdl.StopSimulation'>: No more events
Contributor

jandecaluwe commented May 5, 2015

from multiprocessing import Pool
from myhdl import *

def t(n):
    @instance
    def p():
        for i in range(4):
            yield delay(10)
            print n, now()
    return p

def s(n):
    Simulation(t(n)).run()

p = Pool(4)
p.map(s, (1, 2, 3, 4))
3 10
4 10
3 20
4 20
3 30
4 30
3 40
4 40
<class 'myhdl.StopSimulation'>: No more events<class 'myhdl.StopSimulation'>: No more events

1 10
2 10
2 20
1 20
2 30
1 30
2 40
1 40
<class 'myhdl.StopSimulation'>: No more events<class 'myhdl.StopSimulation'>: No more events
@jpcaram

This comment has been minimized.

Show comment
Hide comment
@jpcaram

jpcaram May 5, 2015

@jandecaluwe , I get your point.

The problem is that we are referring to two different kinds of users. One is the end-user group (group A), the digital designers, and others doing basic logic and behavioral design and simulation. The other group (group B) are those trying to take MyHDL to the next level, trying to re-use it for bigger, more complicated tasks.

MyHDL does great with group A, and perhaps this is why it's been so successful. But the people that you will find involved in a discussion like this are probably going to be mostly from group B.

I'm in group B. I'm developing a Mixed-Signal simulator integrating NG-Spice and MyHDL. For this, I need to do some very non-group-A things, like running multiple simulations simultaneously (different models, or same model, running at different simulation times), exchanging state information between them, making copies of a simulation/model on-the-fly, and even looking at the simulation scheduler to "predict" the next event time.

I'm clearly a minority, but my intended end-product, the mixed-signal simulator, is targeted to the mixed-signal community's group A. I also want the clean an easy to adopt syntax and performance.

We can continue to come up with examples and counter examples, but it would be good to agree on the fact that we all want to contribute to the project and make it better. And I think there is room for improvement.

jpcaram commented May 5, 2015

@jandecaluwe , I get your point.

The problem is that we are referring to two different kinds of users. One is the end-user group (group A), the digital designers, and others doing basic logic and behavioral design and simulation. The other group (group B) are those trying to take MyHDL to the next level, trying to re-use it for bigger, more complicated tasks.

MyHDL does great with group A, and perhaps this is why it's been so successful. But the people that you will find involved in a discussion like this are probably going to be mostly from group B.

I'm in group B. I'm developing a Mixed-Signal simulator integrating NG-Spice and MyHDL. For this, I need to do some very non-group-A things, like running multiple simulations simultaneously (different models, or same model, running at different simulation times), exchanging state information between them, making copies of a simulation/model on-the-fly, and even looking at the simulation scheduler to "predict" the next event time.

I'm clearly a minority, but my intended end-product, the mixed-signal simulator, is targeted to the mixed-signal community's group A. I also want the clean an easy to adopt syntax and performance.

We can continue to come up with examples and counter examples, but it would be good to agree on the fact that we all want to contribute to the project and make it better. And I think there is room for improvement.

@cfelton

This comment has been minimized.

Show comment
Hide comment
@cfelton

cfelton May 5, 2015

Member

@jpcaram

why do you say "required global state to make sure only one simulator is running at a time". I don't think global states are a requirement and that a having a single simulator at a time has to be ensured

Sounds great, if global state is not required to ensure a single instance, I think we would be happy to see this solution. A solution that solves the global state and still enforces a single instance.

Keep the issues separate, you indicated global state is not required to ensure a single instance. The second issue, is multiple instances and the solutions that resolve the issues brought up.

Member

cfelton commented May 5, 2015

@jpcaram

why do you say "required global state to make sure only one simulator is running at a time". I don't think global states are a requirement and that a having a single simulator at a time has to be ensured

Sounds great, if global state is not required to ensure a single instance, I think we would be happy to see this solution. A solution that solves the global state and still enforces a single instance.

Keep the issues separate, you indicated global state is not required to ensure a single instance. The second issue, is multiple instances and the solutions that resolve the issues brought up.

@cfelton

This comment has been minimized.

Show comment
Hide comment
@cfelton

cfelton May 5, 2015

Member

@jmgc, @jandecaluwe example is how I would approach the issue to speed up the simulation with multiple simulators as you described.

Member

cfelton commented May 5, 2015

@jmgc, @jandecaluwe example is how I would approach the issue to speed up the simulation with multiple simulators as you described.

@cfelton

This comment has been minimized.

Show comment
Hide comment
@cfelton

cfelton May 5, 2015

Member

@jpcaram

I'm clearly a minority, but my intended end-product, the mixed-signal simulator, is targeted to the mixed-signal community's group A. I also want the clean an easy to adopt syntax and performance.

I don't think there is any reason to feel alone on this issue, we have to make sure a proposed enhancement doesn't overly complicate or break anything. From my perspective few of the issues raised have been addressed.

In addition, there already exists an example were the two user groups have been satisfied:
http://old.myhdl.org/doku.php/projects:mixedmodesimulation

I don't know all the details of the myhdl+eispice example but it appears to have a solution for the type of environment you are trying to develop.

Member

cfelton commented May 5, 2015

@jpcaram

I'm clearly a minority, but my intended end-product, the mixed-signal simulator, is targeted to the mixed-signal community's group A. I also want the clean an easy to adopt syntax and performance.

I don't think there is any reason to feel alone on this issue, we have to make sure a proposed enhancement doesn't overly complicate or break anything. From my perspective few of the issues raised have been addressed.

In addition, there already exists an example were the two user groups have been satisfied:
http://old.myhdl.org/doku.php/projects:mixedmodesimulation

I don't know all the details of the myhdl+eispice example but it appears to have a solution for the type of environment you are trying to develop.

@jpcaram

This comment has been minimized.

Show comment
Hide comment
@jpcaram

jpcaram May 5, 2015

@cfelton
It is not my intention to discuss all the details and complexity of the implementation of a mixed-signal simulator here. The point is that developers will always come up with unforeseen inventive uses when expanding on a library like MyHDL. One example here or there is not enough to say, hey, your use case is already covered! The script in the link only begins to suggest how you might want to start thinking about doing mixed signal simulation. There is far more to it.

What I believe is important is that a piece of software has a structure with re-usability in mind as well as stability. My experience has been needing to "hack" into MyHDL instead of re-using it. Some due to the global variables. This makes it very difficult to embark in a large project with significant investment. As with any tool, if I'm relying on a hack instead of a feature, I cannot trust that the behavior will be the same in the future or that the functionality will be there at all.

I understand that a lot of thought has been put into the development of MyHDL and that the design decisions were there for a reason. Perhaps the choice of global variables provides the better trade-off. Maybe we don't need to change anything, but perhaps just start documenting re-use practices, such that further development is done with these in mind.

jpcaram commented May 5, 2015

@cfelton
It is not my intention to discuss all the details and complexity of the implementation of a mixed-signal simulator here. The point is that developers will always come up with unforeseen inventive uses when expanding on a library like MyHDL. One example here or there is not enough to say, hey, your use case is already covered! The script in the link only begins to suggest how you might want to start thinking about doing mixed signal simulation. There is far more to it.

What I believe is important is that a piece of software has a structure with re-usability in mind as well as stability. My experience has been needing to "hack" into MyHDL instead of re-using it. Some due to the global variables. This makes it very difficult to embark in a large project with significant investment. As with any tool, if I'm relying on a hack instead of a feature, I cannot trust that the behavior will be the same in the future or that the functionality will be there at all.

I understand that a lot of thought has been put into the development of MyHDL and that the design decisions were there for a reason. Perhaps the choice of global variables provides the better trade-off. Maybe we don't need to change anything, but perhaps just start documenting re-use practices, such that further development is done with these in mind.

@jmgc

This comment has been minimized.

Show comment
Hide comment
@jmgc

jmgc May 5, 2015

Contributor

I fully agree with @jpcaram.

Contributor

jmgc commented May 5, 2015

I fully agree with @jpcaram.

@jandecaluwe

This comment has been minimized.

Show comment
Hide comment
@jandecaluwe

jandecaluwe May 5, 2015

Contributor

@jpcaram You did not get my real point, which is that I strongly dislike overly theoretical, speculative and suggestive statements and that I have a strong preference for practical focus.

You also should not label my example as a "counterexample" but for what it is: a hint for a solution that works today and that is likely to be useful for a subset of users and a subset of the problems discussed in this thread. Of course, the advantage of a working example is that it shows that the "overhead" you referred to is really minimal, or at least, anyone can judge how big it really is.

You also still didn't get what I made clear from the start. I dislike globals like you do. I just do not see a clean solution for an API that people (not just me) will find acceptable and that gets rid of them. What I have seen thus far is not encouraging, but I welcome all efforts wholeheartedly and would love to be surprized. But until then, I find it meaningless to compare working solutions with virtual ones.

Contributor

jandecaluwe commented May 5, 2015

@jpcaram You did not get my real point, which is that I strongly dislike overly theoretical, speculative and suggestive statements and that I have a strong preference for practical focus.

You also should not label my example as a "counterexample" but for what it is: a hint for a solution that works today and that is likely to be useful for a subset of users and a subset of the problems discussed in this thread. Of course, the advantage of a working example is that it shows that the "overhead" you referred to is really minimal, or at least, anyone can judge how big it really is.

You also still didn't get what I made clear from the start. I dislike globals like you do. I just do not see a clean solution for an API that people (not just me) will find acceptable and that gets rid of them. What I have seen thus far is not encouraging, but I welcome all efforts wholeheartedly and would love to be surprized. But until then, I find it meaningless to compare working solutions with virtual ones.

@jpcaram

This comment has been minimized.

Show comment
Hide comment
@jpcaram

jpcaram May 5, 2015

@jandecaluwe I though this thread was about getting rid of globals in MyHDL. So far I believe I'm the only one who has suggested some approach on how to do it, including pseudo-code, started a StackOverflow thread (http://stackoverflow.com/questions/30061421/change-reference-to-function-in-run-time-in-python), also provided specific real-world personal examples (iPython and mixed-signal simulator) of where the problem arises. I've also tried to clarify the (my) objectives, i.e. simple syntax for the end-user, speed, re-usability, user-group segmentation. I categorized myself, not a theoretical person, into one of those groups and pointed out trade-offs of favoring one group versus the other. I also located and mentioned the specific variables in question. I've also provided some "virtual" solutions that you might not like, but I though that is what this discussion was for. All this as an attempt to provide a concrete path to an eventual solution, and some focus, which was also a concern early in the thread. These might not be the best solutions or technically correct at all, but I don't see where the theoretical, speculative (that is labeling) and suggestive side of all this is. But I see it is not of your liking.

I'm mostly hearing comments of the sorts of "You...", "You...", "You...", "people don't understand...", "I don't see how that would help...", "not encouraging...", "you don't get it", "I find it meaningless...". I find this to be disrespectful and unappreciative. Not a very nice environment for collaboration.

jpcaram commented May 5, 2015

@jandecaluwe I though this thread was about getting rid of globals in MyHDL. So far I believe I'm the only one who has suggested some approach on how to do it, including pseudo-code, started a StackOverflow thread (http://stackoverflow.com/questions/30061421/change-reference-to-function-in-run-time-in-python), also provided specific real-world personal examples (iPython and mixed-signal simulator) of where the problem arises. I've also tried to clarify the (my) objectives, i.e. simple syntax for the end-user, speed, re-usability, user-group segmentation. I categorized myself, not a theoretical person, into one of those groups and pointed out trade-offs of favoring one group versus the other. I also located and mentioned the specific variables in question. I've also provided some "virtual" solutions that you might not like, but I though that is what this discussion was for. All this as an attempt to provide a concrete path to an eventual solution, and some focus, which was also a concern early in the thread. These might not be the best solutions or technically correct at all, but I don't see where the theoretical, speculative (that is labeling) and suggestive side of all this is. But I see it is not of your liking.

I'm mostly hearing comments of the sorts of "You...", "You...", "You...", "people don't understand...", "I don't see how that would help...", "not encouraging...", "you don't get it", "I find it meaningless...". I find this to be disrespectful and unappreciative. Not a very nice environment for collaboration.

@jandecaluwe jandecaluwe closed this May 6, 2015

@jandecaluwe

This comment has been minimized.

Show comment
Hide comment
@jandecaluwe

jandecaluwe May 6, 2015

Contributor

Please keep github development focused on concrete issues, and have this type of open-ended discussions on the newsgroup or elsewhere.

Contributor

jandecaluwe commented May 6, 2015

Please keep github development focused on concrete issues, and have this type of open-ended discussions on the newsgroup or elsewhere.

@hgomersall

This comment has been minimized.

Show comment
Hide comment
@hgomersall

hgomersall May 15, 2015

Contributor

Hi Jan,

I appreciate the issue is closed, but given a concrete contribution...

I've implemented a solution to this issue here (with most of the changes in _simulator.py).

It works by creating a context which can be used to store all the current simulation variables. So whenever access to the simulation variables is required, the context manager is used:

with _simulator.simulation_context(some_hashable):
    do the simulation stuff here

There is a default context which it falls back to when not inside the context manager.

All the Signals state is stashed inside that context.

It works pretty much as expected and all the existing test pass except for the following two caveats:

  1. The tracing is currently broken. I think this needs more thought on the API side of things - basically the simulation context is not known to the tracer, so it doesn't have access to the relevant settings.
  2. The stashing of the signals is a huge overhead as it happens on every context entry/exit. This can be dramatically simplified I think as most of the time no change has happened to merit a stash or a recall. Also, it's not clear to me what signal state should be stashed. Currently it's including _val and _next, but I think think that is the wrong thing to do.

I have two examples: one working with multiple simulations and another with multi threaded sims.

Contributor

hgomersall commented May 15, 2015

Hi Jan,

I appreciate the issue is closed, but given a concrete contribution...

I've implemented a solution to this issue here (with most of the changes in _simulator.py).

It works by creating a context which can be used to store all the current simulation variables. So whenever access to the simulation variables is required, the context manager is used:

with _simulator.simulation_context(some_hashable):
    do the simulation stuff here

There is a default context which it falls back to when not inside the context manager.

All the Signals state is stashed inside that context.

It works pretty much as expected and all the existing test pass except for the following two caveats:

  1. The tracing is currently broken. I think this needs more thought on the API side of things - basically the simulation context is not known to the tracer, so it doesn't have access to the relevant settings.
  2. The stashing of the signals is a huge overhead as it happens on every context entry/exit. This can be dramatically simplified I think as most of the time no change has happened to merit a stash or a recall. Also, it's not clear to me what signal state should be stashed. Currently it's including _val and _next, but I think think that is the wrong thing to do.

I have two examples: one working with multiple simulations and another with multi threaded sims.

@jandecaluwe

This comment has been minimized.

Show comment
Hide comment
@jandecaluwe

jandecaluwe May 16, 2015

Contributor

==== 2 failed, 292 passed in 812.59 seconds ===
versus
=== 294 passed in 30.68 seconds ===

What solution?

Contributor

jandecaluwe commented May 16, 2015

==== 2 failed, 292 passed in 812.59 seconds ===
versus
=== 294 passed in 30.68 seconds ===

What solution?

@jmgc

This comment has been minimized.

Show comment
Hide comment
@jmgc

jmgc May 16, 2015

Contributor

Dear @hgomersall,

Would it be possible to store a reference the context of a signal inside the own signal?

For example, you can do it storing the context as an attribute.

I think this will avoid having to ask every time for it, as it will be just there, and shall reduce the time by an important factor.

Best,

    Jose M.

El 16/5/2015, a las 4:32, jandecaluwe notifications@github.com escribió:

==== 2 failed, 292 passed in 812.59 seconds ===
versus
=== 294 passed in 30.68 seconds ===

What solution?


Reply to this email directly or view it on GitHub #68 (comment).

Contributor

jmgc commented May 16, 2015

Dear @hgomersall,

Would it be possible to store a reference the context of a signal inside the own signal?

For example, you can do it storing the context as an attribute.

I think this will avoid having to ask every time for it, as it will be just there, and shall reduce the time by an important factor.

Best,

    Jose M.

El 16/5/2015, a las 4:32, jandecaluwe notifications@github.com escribió:

==== 2 failed, 292 passed in 812.59 seconds ===
versus
=== 294 passed in 30.68 seconds ===

What solution?


Reply to this email directly or view it on GitHub #68 (comment).

@jck

This comment has been minimized.

Show comment
Hide comment
@jck

jck May 16, 2015

Contributor

Our scenario is very similar to asyncio . A MyHDL simulation is analogous to an asyncio event loop. In asyncio, coroutines and tasks(such as asyncio.sleep) take the event loop as an optional argument. In our case, each simulation instance would be an event loop.

There are lots of hints in the PEP and the implementation which will help us figure out a clean way to solve this problem.

Contributor

jck commented May 16, 2015

Our scenario is very similar to asyncio . A MyHDL simulation is analogous to an asyncio event loop. In asyncio, coroutines and tasks(such as asyncio.sleep) take the event loop as an optional argument. In our case, each simulation instance would be an event loop.

There are lots of hints in the PEP and the implementation which will help us figure out a clean way to solve this problem.

@hgomersall

This comment has been minimized.

Show comment
Hide comment
@hgomersall

hgomersall May 17, 2015

Contributor

@jandecaluwe I know exactly what is causing the slow down and what is causing the fails. I tried to explain these and why I didn't submit a PR. The point I'm at is (1) there is discussion to be had regarding the precise API (2) I'm not clear whether I would miss something wrt to signal state so that can be made to run in a sensible time (3) Is this a sensible approach

@jmgc I don't see how storing the context as an attribute overcomes the problem of each simulation wanting to store different state...?

@jck Interesting... I'll take a look. Is the solution implemented not clean?

Contributor

hgomersall commented May 17, 2015

@jandecaluwe I know exactly what is causing the slow down and what is causing the fails. I tried to explain these and why I didn't submit a PR. The point I'm at is (1) there is discussion to be had regarding the precise API (2) I'm not clear whether I would miss something wrt to signal state so that can be made to run in a sensible time (3) Is this a sensible approach

@jmgc I don't see how storing the context as an attribute overcomes the problem of each simulation wanting to store different state...?

@jck Interesting... I'll take a look. Is the solution implemented not clean?

@jmgc

This comment has been minimized.

Show comment
Hide comment
@jmgc

jmgc May 17, 2015

Contributor

Dear @hgomersall,

What I tried to say is that it could help to reduce the time, as it is not needed to call every time a function to derive a context. But I have made no tests, so I cannot confirm it.

Best,

    Jose M.

El 17/5/2015, a las 14:54, Henry Gomersall notifications@github.com escribió:

@jandecaluwe https://github.com/jandecaluwe I know exactly what is causing the slow down and what is causing the fails. I tried to explain these and why I didn't submit a PR. The point I'm at is (1) there is discussion to be had regarding the precise API (2) I'm not clear whether I would miss something wrt to signal state so that can be made to run in a sensible time (3) Is this a sensible approach

@jmgc https://github.com/jmgc I don't see how storing the context as an attribute overcomes the problem of each simulation wanting to store different state...?

@jck https://github.com/jck Interesting... I'll take a look. Is the solution implemented not clean?


Reply to this email directly or view it on GitHub #68 (comment).

Contributor

jmgc commented May 17, 2015

Dear @hgomersall,

What I tried to say is that it could help to reduce the time, as it is not needed to call every time a function to derive a context. But I have made no tests, so I cannot confirm it.

Best,

    Jose M.

El 17/5/2015, a las 14:54, Henry Gomersall notifications@github.com escribió:

@jandecaluwe https://github.com/jandecaluwe I know exactly what is causing the slow down and what is causing the fails. I tried to explain these and why I didn't submit a PR. The point I'm at is (1) there is discussion to be had regarding the precise API (2) I'm not clear whether I would miss something wrt to signal state so that can be made to run in a sensible time (3) Is this a sensible approach

@jmgc https://github.com/jmgc I don't see how storing the context as an attribute overcomes the problem of each simulation wanting to store different state...?

@jck https://github.com/jck Interesting... I'll take a look. Is the solution implemented not clean?


Reply to this email directly or view it on GitHub #68 (comment).

@hgomersall

This comment has been minimized.

Show comment
Hide comment
@hgomersall

hgomersall May 17, 2015

Contributor

@jmgc No, sure. I think the point I'm trying to make is that the state needs to be stored with the simulation instance (or as I've implemented it with the simulation context) since each simulation will want to save different things on the Signal (most notably the waiters). I think the speed up will come because the waiters don't really change much, and the state that does (._next and ._val) shouldn't be part of the context at all. This is what my question is about regarding the signal state, is there anything else I should be aware of?

Contributor

hgomersall commented May 17, 2015

@jmgc No, sure. I think the point I'm trying to make is that the state needs to be stored with the simulation instance (or as I've implemented it with the simulation context) since each simulation will want to save different things on the Signal (most notably the waiters). I think the speed up will come because the waiters don't really change much, and the state that does (._next and ._val) shouldn't be part of the context at all. This is what my question is about regarding the signal state, is there anything else I should be aware of?

@GProtoZeroW

This comment has been minimized.

Show comment
Hide comment
@GProtoZeroW

GProtoZeroW Apr 24, 2017

I have no idea if this issue with calling multiple simulations in a single script got resolved from the last post by @hgomersall (and yes I did see the script that showed running multiple sims.) But I have not been able to run multiple sims in a single jupyter notebook; and instead, am having to comment out the sim call and restart the notebook kernel. I am trying to use the 'del' on my simulation and traceSignals objects to try to clear the offending object but I still get the

"TraceSignalsError: Cannot trace multiple instances simultaneously"

error if I try to run another sim. And this is really problematic for me because I am trying to work each chapter of a Verilog book in a single notebook. And I am hoping to somehow use myHDL with the Xilinx pynq. I am using python 3 and myhdl .9 attached is my testing notebook where I am also in the prototyping stage of a python graphing routine for the simulation outputs. The cell where the simulation stuff is in is cell 5, 6, 7; Testing code is in cell 4; and HDL object is in cell 2

(sorry that this is not on GitHub; just getting back into Git and need to get authors permission for book that I am working through before I post this all the GitHub
myHDL PlotMaker.pdf
)

GProtoZeroW commented Apr 24, 2017

I have no idea if this issue with calling multiple simulations in a single script got resolved from the last post by @hgomersall (and yes I did see the script that showed running multiple sims.) But I have not been able to run multiple sims in a single jupyter notebook; and instead, am having to comment out the sim call and restart the notebook kernel. I am trying to use the 'del' on my simulation and traceSignals objects to try to clear the offending object but I still get the

"TraceSignalsError: Cannot trace multiple instances simultaneously"

error if I try to run another sim. And this is really problematic for me because I am trying to work each chapter of a Verilog book in a single notebook. And I am hoping to somehow use myHDL with the Xilinx pynq. I am using python 3 and myhdl .9 attached is my testing notebook where I am also in the prototyping stage of a python graphing routine for the simulation outputs. The cell where the simulation stuff is in is cell 5, 6, 7; Testing code is in cell 4; and HDL object is in cell 2

(sorry that this is not on GitHub; just getting back into Git and need to get authors permission for book that I am working through before I post this all the GitHub
myHDL PlotMaker.pdf
)

@cfelton

This comment has been minimized.

Show comment
Hide comment
@cfelton

cfelton Apr 26, 2017

Member

@GProtoZeroW when you use the timesteps (only run the simulation for a specific number of sim cycles) the simulator doesn't quit/finalize, because it is available to run more cycles (run n cycles, then run n more cycles). When using the duration parameter (number of sim cycles to run) you have to use the quit function at the end of your simulation.

It doesn't look like this is documented in the manual - we will add it to the todo list for the next release.

Member

cfelton commented Apr 26, 2017

@GProtoZeroW when you use the timesteps (only run the simulation for a specific number of sim cycles) the simulator doesn't quit/finalize, because it is available to run more cycles (run n cycles, then run n more cycles). When using the duration parameter (number of sim cycles to run) you have to use the quit function at the end of your simulation.

It doesn't look like this is documented in the manual - we will add it to the todo list for the next release.

@GProtoZeroW

This comment has been minimized.

Show comment
Hide comment
@GProtoZeroW

GProtoZeroW commented Apr 26, 2017

@cfelton, thanks

@GProtoZeroW

This comment has been minimized.

Show comment
Hide comment
@GProtoZeroW

GProtoZeroW Apr 27, 2017

@cfelton added the "sim.run(10, quiet=1)" and that is not the cause. The cause is in the "traceSignals" object that needs to disconnect from the vcd file after the simulation has ended and then needs to allow its self to be deleted, or at least overridden when called again. I tried adding a '.delete()' to my tracesignals instance after doing sim.run(10, quite=1) and its saying its a tuple?

GProtoZeroW commented Apr 27, 2017

@cfelton added the "sim.run(10, quiet=1)" and that is not the cause. The cause is in the "traceSignals" object that needs to disconnect from the vcd file after the simulation has ended and then needs to allow its self to be deleted, or at least overridden when called again. I tried adding a '.delete()' to my tracesignals instance after doing sim.run(10, quite=1) and its saying its a tuple?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment