myhdl-list Mailing List for MyHDL (Page 192)
Brought to you by:
jandecaluwe
You can subscribe to this list here.
2003 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(14) |
Nov
(4) |
Dec
|
---|---|---|---|---|---|---|---|---|---|---|---|---|
2004 |
Jan
(1) |
Feb
(10) |
Mar
(19) |
Apr
(14) |
May
(1) |
Jun
(4) |
Jul
(10) |
Aug
|
Sep
(2) |
Oct
(7) |
Nov
(17) |
Dec
(12) |
2005 |
Jan
(6) |
Feb
(10) |
Mar
(17) |
Apr
(10) |
May
(9) |
Jun
(5) |
Jul
(26) |
Aug
(34) |
Sep
(10) |
Oct
(38) |
Nov
(71) |
Dec
(74) |
2006 |
Jan
(20) |
Feb
(20) |
Mar
(7) |
Apr
(2) |
May
(13) |
Jun
|
Jul
|
Aug
(4) |
Sep
(37) |
Oct
(43) |
Nov
(30) |
Dec
(33) |
2007 |
Jan
(3) |
Feb
|
Mar
|
Apr
|
May
(30) |
Jun
(9) |
Jul
(1) |
Aug
|
Sep
(8) |
Oct
(13) |
Nov
|
Dec
(4) |
2008 |
Jan
(13) |
Feb
(46) |
Mar
(25) |
Apr
(7) |
May
(20) |
Jun
(73) |
Jul
(38) |
Aug
(47) |
Sep
(24) |
Oct
(18) |
Nov
(9) |
Dec
(36) |
2009 |
Jan
(31) |
Feb
(24) |
Mar
(73) |
Apr
(13) |
May
(47) |
Jun
(28) |
Jul
(36) |
Aug
(2) |
Sep
(5) |
Oct
(8) |
Nov
(16) |
Dec
(29) |
2010 |
Jan
(34) |
Feb
(18) |
Mar
(18) |
Apr
(5) |
May
|
Jun
(24) |
Jul
(53) |
Aug
(3) |
Sep
(18) |
Oct
(33) |
Nov
(19) |
Dec
(15) |
2011 |
Jan
(9) |
Feb
(4) |
Mar
(39) |
Apr
(213) |
May
(86) |
Jun
(46) |
Jul
(22) |
Aug
(11) |
Sep
(78) |
Oct
(59) |
Nov
(38) |
Dec
(24) |
2012 |
Jan
(9) |
Feb
(22) |
Mar
(89) |
Apr
(55) |
May
(222) |
Jun
(86) |
Jul
(57) |
Aug
(32) |
Sep
(49) |
Oct
(69) |
Nov
(12) |
Dec
(35) |
2013 |
Jan
(67) |
Feb
(39) |
Mar
(18) |
Apr
(42) |
May
(79) |
Jun
(1) |
Jul
(19) |
Aug
(18) |
Sep
(54) |
Oct
(79) |
Nov
(9) |
Dec
(26) |
2014 |
Jan
(30) |
Feb
(44) |
Mar
(26) |
Apr
(11) |
May
(39) |
Jun
(1) |
Jul
(89) |
Aug
(15) |
Sep
(7) |
Oct
(6) |
Nov
(20) |
Dec
(27) |
2015 |
Jan
(107) |
Feb
(106) |
Mar
(130) |
Apr
(90) |
May
(147) |
Jun
(28) |
Jul
(53) |
Aug
(16) |
Sep
(23) |
Oct
(7) |
Nov
|
Dec
(16) |
2016 |
Jan
(86) |
Feb
(41) |
Mar
(38) |
Apr
(31) |
May
(37) |
Jun
(11) |
Jul
(1) |
Aug
(1) |
Sep
(3) |
Oct
(1) |
Nov
(5) |
Dec
(3) |
2017 |
Jan
|
Feb
(4) |
Mar
(2) |
Apr
(2) |
May
|
Jun
(3) |
Jul
(2) |
Aug
(2) |
Sep
(1) |
Oct
(2) |
Nov
(1) |
Dec
(1) |
2018 |
Jan
(1) |
Feb
(1) |
Mar
(7) |
Apr
(1) |
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2019 |
Jan
(1) |
Feb
|
Mar
(2) |
Apr
(1) |
May
(1) |
Jun
(2) |
Jul
|
Aug
|
Sep
(1) |
Oct
|
Nov
(3) |
Dec
|
2020 |
Jan
(1) |
Feb
(2) |
Mar
|
Apr
(1) |
May
|
Jun
|
Jul
(1) |
Aug
(1) |
Sep
(1) |
Oct
|
Nov
|
Dec
(3) |
2021 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
(1) |
Jul
(2) |
Aug
|
Sep
|
Oct
|
Nov
(12) |
Dec
(11) |
2022 |
Jan
(7) |
Feb
(2) |
Mar
(1) |
Apr
|
May
|
Jun
(1) |
Jul
(3) |
Aug
(2) |
Sep
(1) |
Oct
|
Nov
|
Dec
(1) |
2023 |
Jan
|
Feb
(1) |
Mar
(1) |
Apr
(3) |
May
|
Jun
|
Jul
|
Aug
(1) |
Sep
|
Oct
|
Nov
|
Dec
(1) |
2024 |
Jan
(1) |
Feb
(2) |
Mar
(4) |
Apr
(2) |
May
(2) |
Jun
(1) |
Jul
|
Aug
(1) |
Sep
(1) |
Oct
|
Nov
|
Dec
(2) |
2025 |
Jan
(1) |
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: Nick P. <np...@in...> - 2003-10-08 12:30:35
|
As a toy-project, to help me get acquainted with myhdl, I wrote this simple MU0-CPU simulator. From the comments in "mu0.py": # # mu0.py # # MU0-processor simulator in MyHDL # # One of the world's first computers (in the modern sense) was the # Small Scale Experimental Machine (SSEM) built by the University of # Manchester, around 1948. While it was originally built using # valves, and could fill a reasonably sized room, it's gate-count was # relatively low, and its architecture had to be very simple. The SSEM # was also experimental, so it was used as the basis of an evolving # design which later became the Manchester Mark I. # # For more information on the SSEM, take a look at: # # http://www.computer50.org/ # # MU0 is an abstract machine based on SSEM. It is a complete processor # specification and it is quite capable of running useful # programs. Its architecture is so simple that a functioning simulator # can be constructed---by a complete novice like myself---in a couple of # days. So almost 55 years after the original SSEM's inspection, and # as a toy project for improving my skills in Python and MyHDL, I # decided to write this simple model of the legendary machine. I hope # you will enjoy playing with it, as much as I did writing it. # # Tested with python-2.3.1 and myhdl-0.3, on a x86 box running Linux. # # Invocation: # # cp mul.mu0 ram.mu0 # python ./mu0.py # # The simulator expects to find a file called "ram.mu0" in the current # directory, containing mu0 symbolic assembly (see the docstring of # the "load_ram" function for the details of the assembler syntax). # It assembles the contents of the file and initializes the processor # memory. Execution starts at address 0. The accumulator is also # initialized at 0. # # version 0.1, 29 Sep 2003 # - Initial version # # version 0.2, 7 Oct 2003 # - Made RAM latch the address, and drive or read the data-bus # at the falling-edge (negedge) of the clock. Before that RAM was # kind-of combinational. # - Remodeled the CU as a combinational block. # - Added a 'state' internal register, that keeps the current state of # the processor's FSM. 'state' is update by the CU. # - Moved all the MU0-construction code into a 'gen_mu0' function. # - Better 'intbv' use (slicing instead of masks) # - Added a tracer-block that prints the instructions executed when # its debugging control is enabled # - Wrote a unit-testing module for MU0. It is implemented in the # file: "mu0_test.py" # # by Nick Patavalis (np...@in...) # # The "mu0 simulator" is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # USA # Comments regarding its operation, its design, as well as suggestions for possible improvements---in style and functionality---are very welcome. /npat P.S. I don't know if it is ok, or even technically possible, to post messages with attachments to this list; but since it's a rather small file, I'll do it anyway. If it doesn't get through, or if it is against the customs of the list (please drop me a line, let me know) I'll see that any future announcements will only contain URL's to downloadable sources. I'm not doing this know as I don't have a readily-available place where to put publicly-accessible stuff. -- All parts should go together without forcing. You must remember that the parts you are reassembling were disassembled by you. Therefore, if you can't get them together again, there must be a reason. By all means, do not use a hammer. -- IBM maintenance manual, 1925 |
From: Jan D. <ja...@ja...> - 2003-10-08 10:52:19
|
Nick Patavalis wrote: > Imagine a high-level block ("superblock"), with an instantiation > function defined like this: > > def gen_superblock(sig1, sig2, sig3): > s1 = Signal(...) > s2 = Signal(...) > ... > s100 = Signal(...) > > fb = [] > fb.append(gen_simpleblock1(sig1, s1, s2, s30) > fb.append(gen_simpleblock2(s1, sig2, s7, sig1) > fb.append(gen_simpleblock1(s10, s20, s30, sig3) > ... > return fb > > As you can see this block is connected to some "external" signals > given as arguments to its instantiation function (here: "sig1", > "sig2", "sig3"). Internally "gen_superblock" creates several > "internal" signals (s1, s2, ..., s100) and instantiates many simpler > blocks connecting them to the external and internal signals. It finaly > returns the list of the instantiated blocks to the caller. > > Now assume that for some reason (and I can think of several such > reasons), the block wants to **expose** some of its internal signals, > so that other blocks can connect to them, should they wish to. The > obvious solution is to consider the exposed signals as external, and > have them supplied by the caller (as arguments to superblock's > instantiation function). While this is technically sufficient, it > doesn't "map" to the concept of "exposing" very well. By treating the > exposed signals as external, it's like saying that they're not > internal to the block anymore, that they *must* be supplied by the > caller, that the caller *must* take the burden of creating and > initializing them. But most typical callers should not need to worry > (or even know much) about these "exposed" signals. > > Another approach would be to treat exposed signals like this (assume > you want to expose s10, s20, s30, ... s100): > > def gen_superblock(sig1, sig1, sig2, sig3): > s1 = Signal(...) > s2 = Signal(...) > ... > s100 = Signal(...) > > fb = [] > fb.append(gen_simpleblock1(sig1, s1, s2, s30) > fb.append(gen_simpleblock2(s1, sig2, s7, sig1) > fb.append(gen_simpleblock1(s10, s20, s30, sig3) > ... > > class sigs_exposed: pass > exposed = sigs_exposed() > exposed.s10 = s10 > exposed.s20 = s20 > exposed.s30 = s30 > ... > exposed.s100 = s100 > > return fb, exp > > Now, ordinary callers don't need to worry about the exposed signals, > they can simply ignore the second return-value like this: > > supeblock, dummy = gen_superblock(sig1, sig2, sig3) > > or even more blatantly like this: > > supeblock = gen_superblock(sig1, sig2, sig3)[0] > > but still these signals can be used by callers knowing a bit more > about the inner-workings of "superblock", like for example by testing > or tracing blocks. > > This approach looks very clean, and very "pythonic" to > me. Unfortunately it breaks the almost-explicit assumption that > instantiation functions must return *only* the instantiated blocks, > and cannot return additional information about them. > > Any comments welcome. This is a reasonably (and anticipated) request, which should have an even more pythonic solution! Some background: - in MyHDL, an instance is modeled as a (nested) sequence (of generators). One way to create them is to return them from functions. However, this is not and should not be a requirement. - one can start with MyHDL without having to know anything about classes, which is nice I think. However, classes are of course available to accomplish more interesting things. - since Python2.2, it is possible to subclass built-in Python types. The way I envisage to solve this is therefore to model a module as a class that inherits from 'list', instead of as a function, e.g. as follows: class gen_superblock(list): def __init__(self, sig1, sig2, sig3): self.s1 = s1 = Signal(...) self.s2 = s2 = Signal(...) ... self.s100 = s100 = Signal(...) fb = [] fb.append(gen_simpleblock1(sig1, s1, s2, s30) fb.append(gen_simpleblock2(s1, sig2, s7, sig1) fb.append(gen_simpleblock1(s10, s20, s30, sig3) ... self[:] = fb So, the desired signals will be available as attributes of the instance. Moreover, any other interesting thing may be made available in the same way. And, this should work with MyHDL as it stands today. Caution: though I anticipated this style in the implementation, I have not tried it myself yet. Regards, Jan -- Jan Decaluwe - Resources bvba - http://jandecaluwe.com Losbergenlaan 16, B-3010 Leuven, Belgium Bored with EDA the way it is? Check this: http://jandecaluwe.com/Tools/MyHDL/Overview.html |
From: Jan D. <ja...@ja...> - 2003-10-07 21:00:43
|
I registered the myhdl mailing list on gmane.org, for those who prefer a newsgroup interface (such as myself). Sourceforge promises to have this also in the future for their mailing lists, but in this way we have it sooner than I expected. This is posted from that newsgroup as a test. Regards, Jan - thanks Thomas for the suggestion. -- Jan Decaluwe - Resources bvba - http://jandecaluwe.com Losbergenlaan 16, B-3010 Leuven, Belgium Bored with EDA the way it is? Check this: http://jandecaluwe.com/Tools/MyHDL/Overview.html |
From: Nick P. <np...@in...> - 2003-10-07 12:30:06
|
On Tue, Oct 07, 2003 at 11:28:52AM +0200, Jan Decaluwe wrote: > > Yes, sorry, I got carried away with implementation issues. > In fact, the real question to you is: is it important that > you can schedule signal updates pre Simulation construction > time, or can you live with the way it is now. > No, scheduling updates before the construction of Simulation is not important. I'm perfectly ok with being able to schedule events after constructing but before starting the simulation. > > They cannot (in a single thread) nor would this be intended behavior. > The only issue is that a suspended simulation may have pending events. > In the implementation, the event lists are "global" - they don't belong > to the Simulation object. The only problem is that pending events from > a suspended simulation should not carry over to a new fresh one. > Oh, now I see. Before starting a simulation, one should make sure that there are no "residue" signal-updates from a *previous* simulation run. If this previous run is from the same simulation-object, then it's ok to simply resume. If it's from another object then it would be better to "clear" any pending updates. Currently you achieve this by clearing all pending updates when the simulation is constructed: This is ok: sim1 = Simulation(...) sim1.run(100) <------------------ suspended sim1.run(100) <---------- safe! sim1 = Simulation(...) sim1.run(100) <------------------ suspended sim2 = Simulation(...) <------------------ pending events cleared sin2.run(100) <---------- safe! But what if: sim1 = Simulation(...) sim2 = Simulation(..) sim1.run(100) <------------------ suspended sin2.run(100) <---------- not safe! If I'm getting this right, then I would personally prefer to have the least amount of "hidden" behavior. That is no hidden global "simulation object registries and such". Furthermore I would lean towards doing everything explicitly (though not very strongly). Something like this: sim1 = Simulation() <---- scheduled updates not cleared sim1.clear() <---- clear pending updates sim1.run() Better still, since scheduled updates are *global* "clear" should not be a method of the simulation object: sim1 = Simulation() <---- scheduled updates not cleared sim_clear_pending() <---- clear pending updates sim1.run() /npat -- A commune is where people join together to share their lack of wealth. -- Richard M. Stallman |
From: Jan D. <ja...@ja...> - 2003-10-07 09:48:19
|
Nick Patavalis wrote: > On Mon, Oct 06, 2003 at 08:50:24PM +0200, Jan Decaluwe wrote: > >>Nick Patavalis wrote: >> >>>Why doesn't sim.run() or the Simulation() construction simply set "sig.val >>>= sig.next" before starting? >> >>sim.run() will cause this for all signals that are in the list of >>signals to be updated, as usual. As long as signal assigments are >>done after Simulation construction, they should work as expected. >> > > > As long as this is a "sanctioned" feature, and not an implementation > by-product, then I'm fully covered! (in your previous post you seemed > to imply the later, rather than the former). It's a feature :-), no problem. > What I still fail to see, is that since you *do* allow signals to be > scheduled for update before a "sim.run()", how would this be different > if you *also* allowed signals to be scheduled for update before the > simulation construction? I could do that, as long as I can make sure that no pending events from a previous Simulation carry over to the next one. > > >>>To state it differently what I would like to do, is: >>> >>>A function creates some signals, instantiates some blocks, and >>>connects them to the signals. Obviously the signals have some default >>>initial values. The function then returns the instances (the >>>generators) and the signals (some of them) to the caller. The caller >>>changes the *initial values* of some of the signals returned to it, >>>and starts the simulation. >>> >>>>From what you say this isn't possible. >> >>All this should be possible! However the paragraph above seems to >>touch another issue: exposing internal signals, as you have described >>in another post - correct? I will answer that issue there. > > > Yes, indeed. Lets keep things separate. > > >>Coming back to the original issue. The implementation is perhaps >>overly restrictive by always clearing the signals-to-be-updated list >>in a Simulation construction. What I want to avoid is that pending >>events from a suspended simulation interfere with a new one. But this >>can also be done as follows: >> >>- a Simulation construction does not clear the list, but bails out >>with an error when it is not empty; >> >>... AND there is a still another >>non-stopped Simulation object around. (Otherwise there would be no gain.) >> >>- a Simulation that stops "naturally" should not have any pending >>events, so the list should be empty (check with an assertion); >>- a suspended simulation can have pending events because it can be >>resumed. Add a stop() method to the Simulation class that clears >>the list and makes the Simulation unrunnable. Thus: suspended >>simulations need to be stopped explicitly before a new Simulation >>can be constructed. >> > > > Sorry but this is a bit over my head! Yes, sorry, I got carried away with implementation issues. In fact, the real question to you is: is it important that you can schedule signal updates pre Simulation construction time, or can you live with the way it is now. > How exactly do you define a "stopped" and how a "suspended" > simulation? How can a simulation enter one or the other state? > Furthermore, how can a simulation know at construction-time whether > there *is* another simulation around (let alone know whether it is > stopped or not)? A Simulation constructor could register it's object in some "global" (user-hidden of course) place. > > I assume that "stopped" is a simulation that finished its > "sim.run(1000)", and returned; so there are no related signals for > which "sig.val != sig.next", so to speak. In this sense a stopped > simulation is in no-way different from a just-constructed, never-ran > simulation. > > A suspended simulation, on the other hand, should be one which was > stopped by a "StopSimulation" exception, so for some related signals > (the ones modified by the block that raised the exception) it might be > that "sig.val != sig.next". Mm, the way I defined it, it's the other way around. "Stopped" is what happens when all events are exhausted, or when a StopSimulation exception is raised by the user. Such as simulation cannot be resumed; it's done forever. "Suspended" is when there are still pending events, but the specified duration has been reached. Such a simulation can be resumed. > But wait! I have more fundamental problems than this! > > Assuming that you have two simulation objects (in the same interpreter > I presume), how can they *both* be running at the same time? How could > they interact? They cannot (in a single thread) nor would this be intended behavior. The only issue is that a suspended simulation may have pending events. In the implementation, the event lists are "global" - they don't belong to the Simulation object. The only problem is that pending events from a suspended simulation should not carry over to a new fresh one. In fact, as long as there is a living, suspended simulation, it should not be possible to create a new one - I think I'll need to implement that. -- Jan Decaluwe - Resources bvba - http://jandecaluwe.com Losbergenlaan 16, B-3010 Leuven, Belgium Bored with EDA the way it is? Check this: http://jandecaluwe.com/Tools/MyHDL/Overview.html |
From: Nick P. <np...@in...> - 2003-10-06 20:17:14
|
On Mon, Oct 06, 2003 at 08:50:24PM +0200, Jan Decaluwe wrote: > Nick Patavalis wrote: > >Why doesn't sim.run() or the Simulation() construction simply set "sig.val > >= sig.next" before starting? > > sim.run() will cause this for all signals that are in the list of > signals to be updated, as usual. As long as signal assigments are > done after Simulation construction, they should work as expected. > As long as this is a "sanctioned" feature, and not an implementation by-product, then I'm fully covered! (in your previous post you seemed to imply the later, rather than the former). What I still fail to see, is that since you *do* allow signals to be scheduled for update before a "sim.run()", how would this be different if you *also* allowed signals to be scheduled for update before the simulation construction? > >To state it differently what I would like to do, is: > > > >A function creates some signals, instantiates some blocks, and > >connects them to the signals. Obviously the signals have some default > >initial values. The function then returns the instances (the > >generators) and the signals (some of them) to the caller. The caller > >changes the *initial values* of some of the signals returned to it, > >and starts the simulation. > > > >>From what you say this isn't possible. > > All this should be possible! However the paragraph above seems to > touch another issue: exposing internal signals, as you have described > in another post - correct? I will answer that issue there. Yes, indeed. Lets keep things separate. > Coming back to the original issue. The implementation is perhaps > overly restrictive by always clearing the signals-to-be-updated list > in a Simulation construction. What I want to avoid is that pending > events from a suspended simulation interfere with a new one. But this > can also be done as follows: > > - a Simulation construction does not clear the list, but bails out > with an error when it is not empty; > > ... AND there is a still another > non-stopped Simulation object around. (Otherwise there would be no gain.) > > - a Simulation that stops "naturally" should not have any pending > events, so the list should be empty (check with an assertion); > - a suspended simulation can have pending events because it can be > resumed. Add a stop() method to the Simulation class that clears > the list and makes the Simulation unrunnable. Thus: suspended > simulations need to be stopped explicitly before a new Simulation > can be constructed. > Sorry but this is a bit over my head! How exactly do you define a "stopped" and how a "suspended" simulation? How can a simulation enter one or the other state? Furthermore, how can a simulation know at construction-time whether there *is* another simulation around (let alone know whether it is stopped or not)? I assume that "stopped" is a simulation that finished its "sim.run(1000)", and returned; so there are no related signals for which "sig.val != sig.next", so to speak. In this sense a stopped simulation is in no-way different from a just-constructed, never-ran simulation. A suspended simulation, on the other hand, should be one which was stopped by a "StopSimulation" exception, so for some related signals (the ones modified by the block that raised the exception) it might be that "sig.val != sig.next". But wait! I have more fundamental problems than this! Assuming that you have two simulation objects (in the same interpreter I presume), how can they *both* be running at the same time? How could they interact? /npat -- Developing skills that depend on a proprietary product makes you a sharecropper on your own brain. -- Donald B. Marti Jr. |
From: Jan D. <ja...@ja...> - 2003-10-06 19:03:13
|
Jan Decaluwe wrote: [Correction] > > Coming back to the original issue. The implementation is perhaps > overly restrictive by always clearing the signals-to-be-updated list > in a Simulation construction. What I want to avoid is that pending > events from a suspended simulation interfere with a new one. But this > can also be done as follows: > > - a Simulation construction does not clear the list, but bails out > with an error when it is not empty ... AND there is a still another non-stopped Simulation object around. (Otherwise there would be no gain.) > - a Simulation that stops "naturally" should not have any pending > events, so the list should be empty (check with an assertion); > - a suspended simulation can have pending events because it can be > resumed. Add a stop() method to the Simulation class that clears > the list and makes the Simulation unrunnable. Thus: suspended > simulations need to be stopped explicitly before a new Simulation > can be constructed. > > What do you think? > -- Jan Decaluwe - Resources bvba - http://jandecaluwe.com Losbergenlaan 16, B-3010 Leuven, Belgium Bored with EDA the way it is? Check this: http://jandecaluwe.com/Tools/MyHDL/Overview.html |
From: Jan D. <ja...@ja...> - 2003-10-06 18:51:03
|
Nick Patavalis wrote: > On Sun, Oct 05, 2003 at 09:55:58PM +0200, Jan Decaluwe wrote: > >>Nick Patavalis wrote: >> >>The confusion can be avoided by only accessing 'next' >>attributes after Simulation construction. My implicit >>HDL-inspired assumption is even that this should only >>happen after starting the simulation. This is easily >>implemented by only accessing a signal's 'next' >>attribute within generators registered with the Simulation. >> > > > My intention was for it to be possible to control the "debugging" > behavior of blocks, *while* the simulation is running (f.e. when a > complex system enters a certain state, then a special block that > monitors this enables the "debugging" controls of other blocks). Of > course in the simplest case I would like to be able to *initialize* > the debugging signals before starting the simulation, without having a > special block for this. What I'm looking for is a way to set initial > signal values at a post-construction, but pre-simulation time. [terminology note: in the following, I will use the term 'signal assignment' to refer to an access to a Signal's 'next' attribute.] Assuming that what you mean is post Simulation construction, that should work with the tool as it stands today. Only assigning signals after simulation start is just how I tend to think about it, but it's not a requirement. Your original issue was caused by a signal assignment pre Simulation construction. > Why doesn't sim.run() or the Simulation() construction simply set "sig.val > = sig.next" before starting? sim.run() will cause this for all signals that are in the list of signals to be updated, as usual. As long as signal assigments are done after Simulation construction, they should work as expected. This would allow one to do things like: > > sig = Signal(bool(0)) > sig.next = 1 > > which would be *functionally identical* to: > > sig = Signal(bool(0)) > sig.val = 1 > > without having to make "val" writable. > > To state it differently what I would like to do, is: > > A function creates some signals, instantiates some blocks, and > connects them to the signals. Obviously the signals have some default > initial values. The function then returns the instances (the > generators) and the signals (some of them) to the caller. The caller > changes the *initial values* of some of the signals returned to it, > and starts the simulation. > >>From what you say this isn't possible. All this should be possible! However the paragraph above seems to touch another issue: exposing internal signals, as you have described in another post - correct? I will answer that issue there. Coming back to the original issue. The implementation is perhaps overly restrictive by always clearing the signals-to-be-updated list in a Simulation construction. What I want to avoid is that pending events from a suspended simulation interfere with a new one. But this can also be done as follows: - a Simulation construction does not clear the list, but bails out with an error when it is not empty; - a Simulation that stops "naturally" should not have any pending events, so the list should be empty (check with an assertion); - a suspended simulation can have pending events because it can be resumed. Add a stop() method to the Simulation class that clears the list and makes the Simulation unrunnable. Thus: suspended simulations need to be stopped explicitly before a new Simulation can be constructed. What do you think? -- Jan Decaluwe - Resources bvba - http://jandecaluwe.com Losbergenlaan 16, B-3010 Leuven, Belgium Bored with EDA the way it is? Check this: http://jandecaluwe.com/Tools/MyHDL/Overview.html |
From: Nick P. <np...@in...> - 2003-10-05 23:25:21
|
Imagine a high-level block ("superblock"), with an instantiation function defined like this: def gen_superblock(sig1, sig2, sig3): s1 = Signal(...) s2 = Signal(...) ... s100 = Signal(...) fb = [] fb.append(gen_simpleblock1(sig1, s1, s2, s30) fb.append(gen_simpleblock2(s1, sig2, s7, sig1) fb.append(gen_simpleblock1(s10, s20, s30, sig3) ... return fb As you can see this block is connected to some "external" signals given as arguments to its instantiation function (here: "sig1", "sig2", "sig3"). Internally "gen_superblock" creates several "internal" signals (s1, s2, ..., s100) and instantiates many simpler blocks connecting them to the external and internal signals. It finaly returns the list of the instantiated blocks to the caller. Now assume that for some reason (and I can think of several such reasons), the block wants to **expose** some of its internal signals, so that other blocks can connect to them, should they wish to. The obvious solution is to consider the exposed signals as external, and have them supplied by the caller (as arguments to superblock's instantiation function). While this is technically sufficient, it doesn't "map" to the concept of "exposing" very well. By treating the exposed signals as external, it's like saying that they're not internal to the block anymore, that they *must* be supplied by the caller, that the caller *must* take the burden of creating and initializing them. But most typical callers should not need to worry (or even know much) about these "exposed" signals. Another approach would be to treat exposed signals like this (assume you want to expose s10, s20, s30, ... s100): def gen_superblock(sig1, sig1, sig2, sig3): s1 = Signal(...) s2 = Signal(...) ... s100 = Signal(...) fb = [] fb.append(gen_simpleblock1(sig1, s1, s2, s30) fb.append(gen_simpleblock2(s1, sig2, s7, sig1) fb.append(gen_simpleblock1(s10, s20, s30, sig3) ... class sigs_exposed: pass exposed = sigs_exposed() exposed.s10 = s10 exposed.s20 = s20 exposed.s30 = s30 ... exposed.s100 = s100 return fb, exp Now, ordinary callers don't need to worry about the exposed signals, they can simply ignore the second return-value like this: supeblock, dummy = gen_superblock(sig1, sig2, sig3) or even more blatantly like this: supeblock = gen_superblock(sig1, sig2, sig3)[0] but still these signals can be used by callers knowing a bit more about the inner-workings of "superblock", like for example by testing or tracing blocks. This approach looks very clean, and very "pythonic" to me. Unfortunately it breaks the almost-explicit assumption that instantiation functions must return *only* the instantiated blocks, and cannot return additional information about them. Any comments welcome. /npat -- Mathematics belongs to God. -- Donald E. Knuth |
From: Nick P. <np...@in...> - 2003-10-05 20:30:36
|
On Sun, Oct 05, 2003 at 09:55:58PM +0200, Jan Decaluwe wrote: > Nick Patavalis wrote: > > The confusion can be avoided by only accessing 'next' > attributes after Simulation construction. My implicit > HDL-inspired assumption is even that this should only > happen after starting the simulation. This is easily > implemented by only accessing a signal's 'next' > attribute within generators registered with the Simulation. > My intention was for it to be possible to control the "debugging" behavior of blocks, *while* the simulation is running (f.e. when a complex system enters a certain state, then a special block that monitors this enables the "debugging" controls of other blocks). Of course in the simplest case I would like to be able to *initialize* the debugging signals before starting the simulation, without having a special block for this. What I'm looking for is a way to set initial signal values at a post-construction, but pre-simulation time. Why doesn't sim.run() or the Simulation() construction simply set "sig.val = sig.next" before starting? This would allow one to do things like: sig = Signal(bool(0)) sig.next = 1 which would be *functionally identical* to: sig = Signal(bool(0)) sig.val = 1 without having to make "val" writable. To state it differently what I would like to do, is: A function creates some signals, instantiates some blocks, and connects them to the signals. Obviously the signals have some default initial values. The function then returns the instances (the generators) and the signals (some of them) to the caller. The caller changes the *initial values* of some of the signals returned to it, and starts the simulation. From what you say this isn't possible. /npat -- Mathematics belongs to God. -- Donald E. Knuth |
From: Jan D. <ja...@ja...> - 2003-10-05 19:56:37
|
Nick Patavalis wrote: > On Mon, Sep 29, 2003 at 09:23:42PM +0200, Jan Decaluwe wrote: > [[[ refers to an off-list discussion ]]] > >>Very nice work! I would gladly add it as an example to future >>MyHDL distributions. >> >>Some upfront comments: >> > > > Sorry for taking so long to answer, but I was engaged in other > activities that kept me away for several days. As I was trying to > address your comments, and write a test-framework for mu0 (which is > turning out very nicely), I came upon this strange behavior: > > from myhdl import * > > def gen_tst (db): > while 1: > yield delay(10) > if db.val: print "now = %d" % (now()) > > def mktst(): > db=Signal(bool(0)) > g = gen_tst(db) > return g, db > > g, db = mktst() > db.next = 1 > sim = Simulation(g) > print "db.val=%d, db.next=%d" % (db.val, db.next) > sim.run(50) > > When I run this, I get: > > $ python2.3 tst.py > db.val=0, db.next=1 > now = 10 > now = 20 > now = 30 > now = 40 > now = 50 > SuspendSimulation: Simulated for duration 50 > > Which is fine. Now, if I comment-out the "print" line like this: > > from myhdl import * > > def gen_tst (db): > while 1: > yield delay(10) > if db.val: print "now = %d" % (now()) > > def mktst(): > db=Signal(bool(0)) > g = gen_tst(db) > return g, db > > g, db = mktst() > db.next = 1 > sim = Simulation(g) > # print "db.val=%d, db.next=%d" % (db.val, db.next) > sim.run(50) > > Then I strangely get: > > $ python2.3 tst.py > SuspendSimulation: Simulated for duration 50 > > Is this supposed to happen? What happens is the following. The Simulation constructor clears a number of lists that are used during simulation. One of these is the list of signals scheduled for updating. This is done to avoid interference between multiple Simulation's that a single program may set up and run. Thus, 'db.next = 1' schedules signal db for updating, but the Simulation constructor clears this. The difference in observed behavior is because a *read* access to 'db.next' also schedules the signal for updating - this is why the print statement makes a difference. Scheduling an update on read access is necessary to support statements like 'sig.next[i] = 1'. Here, the 'next' value is obtained by a read access but may be modified by an index assignment. The confusion can be avoided by only accessing 'next' attributes after Simulation construction. My implicit HDL-inspired assumption is even that this should only happen after starting the simulation. This is easily implemented by only accessing a signal's 'next' attribute within generators registered with the Simulation. In this particular case, I don't think there's a need to use a signal for 'db'. A plain variable or Python's '__debug__' variable should do. Regards, Jan -- Jan Decaluwe - Resources bvba - http://jandecaluwe.com Losbergenlaan 16, B-3010 Leuven, Belgium Bored with EDA the way it is? Check this: http://jandecaluwe.com/Tools/MyHDL/Overview.html |
From: Nick P. <np...@in...> - 2003-10-05 14:40:09
|
On Mon, Sep 29, 2003 at 09:23:42PM +0200, Jan Decaluwe wrote: [[[ refers to an off-list discussion ]]] > > Very nice work! I would gladly add it as an example to future > MyHDL distributions. > > Some upfront comments: > Sorry for taking so long to answer, but I was engaged in other activities that kept me away for several days. As I was trying to address your comments, and write a test-framework for mu0 (which is turning out very nicely), I came upon this strange behavior: from myhdl import * def gen_tst (db): while 1: yield delay(10) if db.val: print "now = %d" % (now()) def mktst(): db=Signal(bool(0)) g = gen_tst(db) return g, db g, db = mktst() db.next = 1 sim = Simulation(g) print "db.val=%d, db.next=%d" % (db.val, db.next) sim.run(50) When I run this, I get: $ python2.3 tst.py db.val=0, db.next=1 now = 10 now = 20 now = 30 now = 40 now = 50 SuspendSimulation: Simulated for duration 50 Which is fine. Now, if I comment-out the "print" line like this: from myhdl import * def gen_tst (db): while 1: yield delay(10) if db.val: print "now = %d" % (now()) def mktst(): db=Signal(bool(0)) g = gen_tst(db) return g, db g, db = mktst() db.next = 1 sim = Simulation(g) # print "db.val=%d, db.next=%d" % (db.val, db.next) sim.run(50) Then I strangely get: $ python2.3 tst.py SuspendSimulation: Simulated for duration 50 Is this supposed to happen? /npat -- But the delight and pride of Aule is in the deed of making, and in the thing made, and neither in possession nor in his own mastery; wherefore he gives and hoards not, and is free from care, passing ever on to some new work." -- J.R.R. Tolkien, Ainulindale (Silmarillion) |
From: Jan D. <ja...@ja...> - 2003-10-01 07:07:37
|
Check that the mailing list works. -- Jan Decaluwe - Resources bvba - http://jandecaluwe.com Losbergenlaan 16, B-3010 Leuven, Belgium Bored with EDA the way it is? Check this: http://jandecaluwe.com/Tools/MyHDL/Overview.html |