Re: [myhdl-list] MEP - keep hierarchy in conversion
Brought to you by:
jandecaluwe
From: Per K. <bas...@gm...> - 2013-10-02 06:47:08
|
Floorplanning is essential. (I could stop here, but I'm in a chatty mood.) Yes, you can do a simple million gate ASIC without floorplanning. But is it more than two decades since a million gate ASIC was anything to write home about. A couple of guys in a garage can do hundred million to trillion gate designs. Sure, they cannot tape it out without doing some serious growing up financially, but how is that going to happen if they cannot show that their design is going to work? Apart from floorplanning a hierarchical netlist is necessary for benchmarking (area, power, routing, timing...). It is nigh impossible to figure out what's going on in your design with a flat netlist. Saying "back-end tools need to improve", is like putting off getting a bike because soon we are all gonna have flying cars. Back end tools have needed to improve for decades. (And they have, but designs have grown faster.) Finally, worrying about target dependence is missing the mark. Every design is target dependent. You can try your best to fit a range of targets, but there is always a dependence. Secondly, the hierarchy is not the floorplan. The hierarchy is just the partition into lego bricks, and thus not very target dependent. The floorplan is how you fit them together. Cheers Per On Wed, Oct 2, 2013 at 12:44 AM, Angel Ezquerra <ang...@gm...>wrote: > I cannot comment on the ASIC side, but on the FPGA side it is a common > recommendation to properly organize your code into entities to improve > the map and/or plan and route results. I believe that it is also > necessary to be able to do incremental builds and what they call > "Partial Reconfiguration", which "is the ability to dynamically modify > blocks of logic by downloading partial bit files while the remaining > logic continues to operate without interruption". > > I'm not saying this is something that Xilinx could not improve (I > really think they could and they should). However, I would not hold my > breath hoping for Xilinx tools to improve in this regard. They are a > little better now, but their tools used to be and still are to a long > extent very rudimentary and finicky. My guess is that they have a lot > of other things that they must improve before getting to this. > > I also think that being able to control how the generated code is > split into files and entities would be nice, particularly if you had > to debug some generation issue. It might also help when adding > chipscope probes. > > Finally, it would make it easier to include generated VHDL or Verilog > files into version control. In general I don't think that generated > VHDL and Verilog files should be put into version control, because > they are derived files that can be generated from the MyHDL sources. > However, some projects have policies that require all VHDL or Verilog > code to be included on the source repository. In those cases having a > single big generated VHDL file is a pain because it changes with every > modification of any of the MyHDL files, and it is hard to tell what > changed in that big single file. If multiple files were generated, > only some of those files would usually change, making it easier to > tell what changed in a given version. > > So I think that there are a few sensible reasons for wanting the > ability to split the generated design into files and entities. > > Cheers, > > Angel > > > On Tue, Oct 1, 2013 at 9:45 PM, Jan Decaluwe <ja...@ja...> wrote: > > A few helicopter-view comments on this. > > > > I still have an issue with floorplanning being that important. > > Afaik we can do million-gate ASICs without floorplanning at > > all. It seems to me an ideal problem for full automation by > > layout tools. > > > > To put it differently, if one really needs floorplanning, I > > would think it applies to very large projects with big > > budgets - more than enough to actually pay someone to > > solve this in MyHDL (me for example :-)). > > > > Of course, FPGAs may be be different. But I still > > would think it's a matter of back-end tools that need > > to improve in the first place - not our task. > > > > So - are we really sure floorplanning actually makes > > a difference? > > > > If it does, I certainly would not want a solution that > > influences the source code significantly, as I think this > > solution is suggesting. It has nothing to do with functionality. > > Instead it would make source code target-dependent, as > > the floorplanning solution for one target may not be right > > or required for another one. > > > > Jan > > > > On 09/29/2013 08:21 PM, David Holl wrote: > >> There was an old thread regarding MEP 110, but I've come up with an > alternative "solution", and I'm looking for your comments. (call it MEP > 110-alt?) > >> > >> tl;dr --- If you're interested, > >> > >> Introduction: Same as MEP 110. (Especially for floor planning...) > >> ----------------------- > >> Analysis: Same as MEP 110. (Yep, everything gets flattened by > default...) > >> ----------------------- > >> Proposed Solution: (with implementation) > >> > >> I did not follow the proposed solution in MEP 110, because that > would've required that I change [any of] my components to be "top-module > convertible". (I'm using a form of signal containers --similar to MEP > 107-- which which would've required many changes (in my code) to achieve > "top-module convertibility".) > >> > >> What I did was I started from the flattened hierarchy in > conversion/_toVerilog.py, but instead of calling the usual _writeSigDecls, > _convertGens, I wrote my own convoluted output code: > >> ... > >> if self.partitioned_output: > >> _write_partitioned_output(self.partitioned_output, > vfile, vpath, self.timescale, h, intf, siglist, memlist, genlist, doc) > >> else: > >> _writeFileHeader(vfile, vpath, self.timescale) > >> _writeModuleHeader(vfile, intf, doc) > >> _writeSigDecls(vfile, intf, siglist, memlist) > >> _convertGens(genlist, vfile) > >> _writeModuleFooter(vfile) > >> ... > >> > >> > >> To activate this alternative output, just set > toVerilog.partitioned_output=True: > >> toVerilog.name='test_partition' > >> toVerilog.partitioned_output=True # the default is False > >> toVerilog(_test_top, clk, AAA, BBB, ZZZ, TTT, VVV) > >> > >> Without any other changes to a hardware description, this alternative > code will produce identical, flattened output. (right down to the arbitrary > ordering of signals and generators...) > >> > >> However, you may now group any related logic together, as needed. I > call a group of logic a "partition", and these partitions may be nested. > Instead of the word "partition" you could call it a "module" instead, > since the concept is almost identical to Verilog module's. In the > following description, it will appear that I'm flipping between "partition" > and "module" when really, I'm describing how that partitions in python > impact the created Verilog modules. (but for simplistic purposes, since I > guarantee each "partition" will create a unique Verilog "module", feel free > to call em' what you want...) > >> > >> There are 2 ways to assign related hardware into partitions. > >> ----------------------- > >> 1) The first is via python's "with" statement. I'll show a few > examples: > >> > >> example 1.a) A simple partition... > >> from myhdl import Signal, partition, ... > >> > >> @always(clk.posedge) > >> def clgc(): > >> c.next = a + b > >> > >> with partition('A'): > >> @always(clk.posedge) > >> def clgd(): > >> d.next = c + e > >> > >> @always(clk.posedge) > >> def clge(): > >> e.next = a * b > >> > >> @always(clk.posedge) > >> def clgf(): > >> f.next = more stuff... > >> > >> > >> What "partition" does is annotate all generators (and shadow > signals...) with your text label. Then the "partitioned-output" code uses > these annotations move related logic into a Verilog module, and instantiate > that module from the top-level module. Module ports are automatically > created for any signals that need to cross between modules. > >> > >> This code still creates only 1 output .v file containing all modules. > (I didn't care if it was 1 file or multiple files, but for me, 1 file was > "easier" to move/copy around in my opinion.) > >> > >> The top module will include all of the signals, except for "e" --- > because in this code, e is only used within partition A. Therefore "e" > will appear as a driven "reg" within a submodule called A. (and that > submodule "A" is instantiated in the top level as "part_A"...) > >> > >> > >> > >> example 1.b) Partitions may be nested. > >> > >> @always(clk.posedge) > >> def clgc(): > >> c.next = a + b > >> > >> with partition('A'): > >> @always(clk.posedge) > >> def clgd(): > >> d.next = c + e > >> > >> with partition('B'): > >> @always(clk.posedge) > >> def clge(): > >> e.next = a * b > >> > >> @always(clk.posedge) > >> def clgf(): > >> f.next = more stuff... > >> > >> > >> This code will create 3 modules total: the top module, a module called > "A", and a module called "A_B". > >> > >> > >> example 1.c) Partitions having the same name will be renamed to stay > unique! > >> > >> If you want related code to be grouped into a partition, all of that > code must be contained in the same python "with" block. For example: > >> > >> from myhdl import Signal, partition, ... > >> > >> @always(clk.posedge) > >> def clgc(): > >> c.next = a + b > >> > >> with partition('A'): # This will be renamed to A0 > >> @always(clk.posedge) > >> def clgd(): > >> d.next = c + e > >> > >> with partition('A'): # This will be renamed to A1 > >> @always(clk.posedge) > >> def clge(): > >> e.next = a * b > >> > >> > >> Rationale: When you start nesting partitions, partition names are > guaranteed to produce unique module instances and not accidentally group > unrelated logic together. > >> > >> > >> example 1.d) Partitions are nestable across your python function calls, > and renaming will happen to keep sub > >> > >> For example, unrelated nested partitions may use the same name without > fear of their logic being accidentally grouped together. > >> > >> from myhdl import Signal, partition, ... > >> > >> def my_module_alice(...): > >> # ... > >> with partition('SM'): > >> # This happens to enclose a state machine. > >> # The name SM isn't descriptive enough, but if you > >> # want descriptive Verilog output, then you should > >> # use descriptive names. > >> # ... > >> # ... > >> return instances() > >> > >> def my_module_bob(...): > >> # ... > >> with partition('SM'):# This encloses an unrelated state machine. > >> # ... > >> # ... > >> return instances() > >> > >> def top(...): > >> @always(clk.posedge) > >> def clgc(): > >> c.next = a + b > >> > >> with partition('CRYPTO'): > >> alice_inst = alice(...) > >> bob0_inst = bob(...) > >> bob1_inst = bob(...) > >> > >> with partition('CRYPTO_SM2'): > >> # I made this CRYPTO_SM2 name, just to be a jerk. > >> @always(clk.posedge) > >> def clgd(): > >> d.next = c + e > >> > >> > >> This code would produce 6 instantiated modules in the generated Verilog > output: > >> module top(...); > >> module CRYPTO(...); > >> module CRYPTO_SM0(...); // this is from alice_inst > >> module CRYPTO_SM1(...); // this is from bob0_inst > >> module CRYPTO_SM2(...); // this is from bob1_inst > >> module CRYPTO_SM2_(...); // renamed CRYPTO_SM2 to not conflict with > CRYPT_SM2 from bob1_inst > >> > >> Admittedly, the generated names CRYPTO_SM... in this example aren't > very clear, but the point here is that your python functions (like alice() > and bob()) have a guaranteed means to group logic into a Verilog module > without accidental commingling of unrelated from other modules. > >> > >> The "top" module instantates "CRYPTO" and "CRYPTO_SM2_". Then "CRYPTO" > instantiates "CRYPTO_SM0", "CRYPTO_SM1", and "CRYPTO_SM2". > >> > >> > >> example 1.e) Partitions support Verilog 2001 attributes (and if > someone wants to add VHDL support...) > >> > >> with partition('A') as this_part: # This will be renamed to A0 > >> this_part.attr_add('KEEP_HIERARCHY', 'TRUE') > >> this_part.attr_add('DONT_TOUCH', 'TRUE') > >> > >> @always(clk.posedge) > >> def clgd(): > >> d.next = c + e > >> > >> This will produce output that instantiates module A as: > >> > >> (* KEEP_HIERARCHY="TRUE", DONT_TOUCH="TRUE" *) part_A A(clk, c, e, d); > >> > >> // The generated module for instance A is called "part_A". > >> > >> (MyHDL also has a nifty feature to include doc strings as embedded > comments. I have some back-end support for attaching a string to a > partition, to be output as a comment in the code, but I haven't turned it > on yet.) > >> > >> ----------------------- > >> 2) The second way to group logic into a partition is with a python > decorator. > >> > >> example 2) Using decorators in addition to "with" blocks. > >> > >> The decorator syntax uses the same rules as the with-blocks. (All > partitions will be unique, and possibly suffixed with a number to maintain > uniqueness in the Verilog code. Partitions may be nested. Use descriptive > names if you want descriptive output.) > >> > >> Here, I'll intermix the decorator and with syntax: > >> > >> def my_module_alice(...): > >> # ... > >> with partition('SM'): > >> # This happens to enclose a state machine. > >> # The name SM isn't descriptive enough, but if you > >> # want descriptive Verilog output, then you should > >> # use descriptive names. > >> # ... > >> # ... > >> return instances() > >> > >> @partition('AES') # <---- partition a la decorator. > >> def my_module_bob(...): > >> # ... > >> with partition('SM'):# This encloses an unrelated state machine. > >> # ... > >> # ... > >> return instances() > >> > >> def top(...): > >> @always(clk.posedge) > >> def clgc(): > >> c.next = a + b > >> > >> with partition('CRYPTO'): > >> alice_inst = alice(...) > >> bob0_inst = bob(...) > >> bob1_inst = bob(...) > >> > >> with partition('CRYPTO_SM2'): > >> # I made this CRYPTO_SM2 name, just to be a jerk. > >> @always(clk.posedge) > >> def clgd(): > >> d.next = c + e > >> > >> The above code will generate ~8 modules: > >> module top(...); > >> module CRYPTO(...); > >> module CRYPTO_SM(...); // this is from alice_inst > >> module CRYPTO_AES0(...); // decorator on bob() > >> module CRYPTO_AES0_SM(...); // this is from bob0_inst > >> module CRYPTO_AES1(...); // decorator on bob() > >> module CRYPTO_AES1_SM(...); // this is from bob1_inst > >> module CRYPTO_SM2(...); // renamed CRYPTO_SM2 to not conflict with > CRYPT.SM <http://CRYPT.SM> from bob1_inst > >> > >> > >> ----------------------- END OF EXAMPLES > >> > >> Limitations: I hope there aren't any. I put enough care to accomodate > ConcatSignal's, _SliceSignal's, const [undriven] _Signal's, etc... And if > a signal gets pushed into a sub-partition where it is both driven and read, > as well as output from that sub-partition, the generator will automatically > make a separate wire just for the output port, that is driven from your > signal. (This prevents "Output port is read internally..." warnings for > partition-generated modules. I don't do this for the top-level though, to > preserve the same interface as current MyHDL output.) > >> > >> Component Conversion: No additional restrictions beyond that of MyHDL. > There is still the same requirement on your top-level to be "top-level > convertible", but there is flexibility for your lower levels. > >> > >> Component Parameters: What parameters? All of your parameters were > already digested by python+MyHDL magic, and I'm operating on the flattened > hierarchy. If you invoke the same sub-partition (sub-module) multiple > times, it will be replicated in the output, but every time it appears, it > will use the globally-unique signal names that MyHDL has already assigned. > (ie, I don't change your signal names.) > >> > >> Any drawbacks: > >> This may/will produce larger output code than the proposed solution in > MEP 110. The existing MEP 110 solution will create 1 copy of each module, > and instantiate it multiple times (as long as each instantiation shares the > same port signal widths, etc...). In contrast, this "110.alt" solution > will create a whole copy of a module every time it is instantiated. (But > each copy inherits the unique signal names assigned by MyHDL's flattening > algorithm.) However, the larger output size from this "110.alt" isn't that > much larger than MyHDL's native flat output. (depending on your signal > usage...) > >> > >> Benefits: > >> You can have hierarchical output with minimal changes to your code, and > you control exactly how your logic is partitioned into the hierarchy. Just > sprinkle a few @partition(...) or "with partition(...):" statements > wherever you need in your design. > >> > >> Known pitfalls: I have not tried or tested TristateSignal's for > "inout" ports, and I've only tested on a very narrow subset of MyHDL's > feature set. (I was was already bitten by ConcatSignal's, _SliceSignal's, > and lists of signals accidentally being inferred as memories... However, I > expect these areas to work as expected now.) > >> > >> > >> But if anyone is interested, here's the code, and I'm open for feedback. > >> > >> I attached patches against myhdl-0.8.tar.gz available from > >> https://sourceforge.net/projects/myhdl/files/myhdl/0.8/ > >> > >> Of the 2 patches, myhdl-0.8-fix_modbv.patch is my poor-man's fix for > modbv, because I needed modbv. This patch is most likely obsoleted by > Jan's real fix in the repo. > >> > >> The other patch (myhdl-0.8-partitions.patch) contains my crude first > draft supporting the described hierarchy. Yes, this code is ugly. Don't > look at it yet. It is a quick mock-up of some functionality I really > wanted. But give it a try if you're interested and let me know what it > breaks on... Or if you really want to dive into the code, feel free to do > so. > >> > >> On my systems, I apply & install these patches as follows: (gunzip the > .patch files first) > >> > >> gunzip myhdl-0.8-fix_modbv.patch.gz > >> gunzip myhdl-0.8-partitions.patch.gz > >> tar zxf myhdl-0.8.tar.gz \ > >> && cd myhdl-0.8 \ > >> && patch -p1 < ../myhdl-0.8-fix_modbv.patch \ > >> && patch -p1 < ../myhdl-0.8-partitions.patch \ > >> && python setup.py build \ > >> && python setup.py install --user -O2 \ > >> && cd .. \ > >> && rm -rf myhdl-0.8 > >> > >> This installs myhdl into python's standard location for my home > directory, but feel free to leave off --user to install to the main system > path, or wherever else you want. > >> > >> To test drive the functionality, try running test_partition.py. Set > >> toVerilog.partitioned_output=False > >> to see the normal output, and > >> toVerilog.partitioned_output=True > >> to see the partitioned output. And if you are curious, try > >> toVerilog.partitioned_output="I promise I will never die." > >> to enable the partitioned output code, but tell it to ignore the > partition annotations. > >> > >> > >> (typos and all, I'm hitting send...) > >> > >> - David > >> > >> > >> > >> On Wed, May 1, 2013 at 6:44 PM, Oscar Daniel Diaz <osc...@gm...<mailto: > osc...@gm...>> wrote: > >> > >> El Wed, 01 May 2013 10:55:55 +0200 > >> Jan Decaluwe <ja...@ja... <mailto:ja...@ja...>> > escribió: > >> > >> > On 04/29/2013 05:25 PM, Oscar Daniel Diaz wrote: > >> > > >> > > Given that the converter is called recursively several times, > >> > > multiple files are generated and its contents are used for > component > >> > > declaration (VHDL). Recursive calls must avoid file > replication (for > >> > > VHDL case means avoid multiple package file generation). This > is > >> > > done by keeping generated code in memory before pushing to > files. > >> > > > >> > > Attribute "no_component_files" : > >> > > * False : all components code is saved to disk as soon as > >> > > possible. > >> > > * True : discard components code, only save top-module file. > >> > > >> > Not sure what is meant here exactly. Why would we need component > >> > declarations, as opposed to simply using direct instantation? > >> > For a case like this, this seems much simpler and less verbose > >> > to me. > >> > >> Since keep hierarchy conversion requires multiple files to generate > >> (top-module and components to instantiate), this flag prevents > >> generation of those components. Suppose you make some changes only > in > >> the top-module, this flag allows to only generate top-module file. > >> > >> When I change from VHDL '87 syntax (doing recursive calls to get > >> component declaration) to '93 syntax, that flag would prevent > >> those recursive calls. > >> > >> -- > >> Oscar Díaz > >> Key Fingerprint = 904B 306C C3C2 7487 650B BFAC EDA2 B702 90E9 9964 > >> gpg --keyserver subkeys.pgp.net <http://subkeys.pgp.net> > --recv-keys 90E99964 > >> > >> > >> _______________________________________________ > >> myhdl-list mailing list > >> myh...@li... <mailto: > myh...@li...> > >> https://lists.sourceforge.net/lists/listinfo/myhdl-list > >> > >> > >> > >> > >> > ------------------------------------------------------------------------------ > >> October Webinars: Code for Performance > >> Free Intel webinars can help you accelerate application performance. > >> Explore tips for MPI, OpenMP, advanced profiling, and more. Get the > most from > >> the latest Intel processors and coprocessors. See abstracts and > register > > >> > http://pubads.g.doubleclick.net/gampad/clk?id=60133471&iu=/4140/ostg.clktrk > >> > >> > >> > >> _______________________________________________ > >> myhdl-list mailing list > >> myh...@li... > >> https://lists.sourceforge.net/lists/listinfo/myhdl-list > >> > > > > > > -- > > Jan Decaluwe - Resources bvba - http://www.jandecaluwe.com > > Python as a HDL: http://www.myhdl.org > > VHDL development, the modern way: http://www.sigasi.com > > World-class digital design: http://www.easics.com > > > > > ------------------------------------------------------------------------------ > > October Webinars: Code for Performance > > Free Intel webinars can help you accelerate application performance. > > Explore tips for MPI, OpenMP, advanced profiling, and more. Get the most > from > > the latest Intel processors and coprocessors. See abstracts and register > > > > > http://pubads.g.doubleclick.net/gampad/clk?id=60134791&iu=/4140/ostg.clktrk > > _______________________________________________ > > myhdl-list mailing list > > myh...@li... > > https://lists.sourceforge.net/lists/listinfo/myhdl-list > > > ------------------------------------------------------------------------------ > October Webinars: Code for Performance > Free Intel webinars can help you accelerate application performance. > Explore tips for MPI, OpenMP, advanced profiling, and more. Get the most > from > the latest Intel processors and coprocessors. See abstracts and register > > http://pubads.g.doubleclick.net/gampad/clk?id=60134791&iu=/4140/ostg.clktrk > _______________________________________________ > myhdl-list mailing list > myh...@li... > https://lists.sourceforge.net/lists/listinfo/myhdl-list > |