Verilog: "Lines of code" versus device utilisation - Page 1
Forum section: electronics / general

author: Cerebus
author_rank: Super Contributor
timestamp: November 07, 2021, 05:16:15 pm
content: I got a pleasant surprise today when my 800 lines of Verilog representing a fairly hairy state machine and rather a lot of counters synthesised to 130 LCs on an iCE40 FPGA.That got me idly wondering if anybody has tracked the relationship between "lines of code" and device utilisation. I know that it's just as specious a metric as it is for imperative programming (C, C++, whatever), but in imperative coding there is, at least for any particular coding style, a rough relationship between code size and source size. Also there are a zillion reasons why it shouldn't hold for Verilog - a single multiply operator could on some architectures easily double the size of the implementation. But still, it made me curious.Has anyone ever tracked the relationship? Does anyone have any good actual examples from real life where the relationship has held, or has most definitely not held?

author: james_s
author_rank: Super Contributor
timestamp: November 07, 2021, 05:43:43 pm
content: From my own (non-professional) experience, it is all over the place and there is very little correlation. Device utilization depends on what circuitry you're describing, not how many lines you use to describe it. It's possible to fill a large FPGA with only a few lines of code if you create a large memory or something of that nature.

author: SiliconWizard
author_rank: Super Contributor
timestamp: November 07, 2021, 07:27:36 pm
content: This is absolutely uncorrelated to a large extent. Can't even be compared to software code. Software code, at least in traditional imperative languages with no metaprogramming (so forget about C++ templates, which will often throw all bets off), has a fair correlation between source code size and object code size.HDL is a completely different beast. As an extreme example, just a few lines of Verilog or VHDL source could yield 100% device utilization.While (again at least traditional) programming languages essentially translate to a sequence of instructions for each statement, HDLs define hardware structures, thus the result is unpredictable from just the amount of statements in the source code.

author: mfro
author_rank: Regular Contributor
timestamp: November 07, 2021, 08:24:12 pm
content: you can write a for loop in one single line that eats up all your resources and hundreds of lines that are optimised away..

author: Cerebus
author_rank: Super Contributor
timestamp: November 07, 2021, 09:16:10 pm
content: So, so far nobody has managed to add anything beyond confirmation of what I already knew and had stated, that you can easily find an artificial way to use up all a device's resources and that there's not any necessary relationshipin theorybetween size of source and size of implementation.However, in the real world things have a way of developing patterns.In practicethere may be some correlations. So, for example, someone with enough experience to draw on might say "Oh yeah. Things that are mostly state machines tend to use up around Y cells for every X lines of code. With DSPish things it's Y * your bit width for X lines of code", and so on. So, has anyone who has done more than dabble (and that dabbler category definitely includes me), seen patterns like this emerge or is it all really as variable as one might naïvely expect?

author: NorthGuy
author_rank: Super Contributor
timestamp: November 07, 2021, 11:33:11 pm
content: I look at this from the opposite end. I envision the hardware which I am supposed to build then I describe it. I can estimate the resource usage to some degree. Some things, such as an adder, are easier to describe, despite they may take quite a bit of logic. Others are not so easy to describe, so you have to write lots and lots of lines, akin of a state machine, to describe a simple logic block which will use very little resources (a.k.a has only few inputs and outputs). That's where the most time is spend and that's where the bugs lurk. Just as with resources, I can estimate how long it would take to write and roughly how many lines I would need to write.

author: rstofer
author_rank: Super Contributor
timestamp: November 07, 2021, 11:37:47 pm
content: Xilinx publishes recommended coding techniques and this is but one of the volumes:https://www.xilinx.com/support/documentation/user_guides/ug474_7Series_CLB.pdfOne would assume that the techniques are aiming toward some optimum (speed or space) but I haven't gotten far enough along to worry about the issue. Bigger devices are cheap enough for my needs.

author: Someone
author_rank: Super Contributor
timestamp: November 08, 2021, 12:52:12 am
content: Quote from: Cerebus on November 07, 2021, 09:16:10 pm"lines" arent a good measure, as discussed above (in the extremes), further its possible to have radically different implementations.Take it back to a simple and common example. How do you implement a delay/timer/saturable counter ? There are many many ways to do it, all with similar amounts of code, but with different resource uses. Some of those will infer faster implementation performance, more readable code, and all of the characteristics will change depending on the specific tool and target architecture.Even just considering a single tool and architecture, lines still won't be a good measure if the different implementations are done "well" or not. So much code I work through doesn't bother to size vectors accurately, or uses convoluted control flows.Rarely do you find those magic programmers who manage to simultaneously make code that is readable, functionally correct, robust, performant, and low resource. Usually pick one or two at best. Readability is usually a balance of lines of code, its the usual goldilocks situation.

author: miken
author_rank: Regular Contributor
timestamp: November 08, 2021, 12:58:08 am
content: It's an intriguing idea but yeah, really depends on what you're doing, and your coding style. I mean, I've dug through orphan legacy code only to find out that most of it was optimized out; that's probably not what you're thinking of but that's what you run into in the real world. You'd also find tons of boilerplate for wires, registers, and such.For small designs where things are easier to keep in one's head it might be more possible to draw a correlation between code and utilization. For large designs I don't find it as interesting since I'm usually battling fanout/routing more than raw resource utilization.Given the wide range of styles out there I overall don't feel it's gonna be that useful of a concept.

author: Cerebus
author_rank: Super Contributor
timestamp: November 08, 2021, 02:50:29 am
content: Quote from: miken on November 08, 2021, 12:58:08 amAs I started with "I know that it's just as specious a metric as it is for imperative programming" I didn't imagine that it would beuseful. I was just curious what observations along that line people might have made in practice, if any. So far you're the only person to cite practical experience as the basis of their comments.

author: NorthGuy
author_rank: Super Contributor
timestamp: November 08, 2021, 02:59:56 am
content: Quote from: Someone on November 08, 2021, 12:52:12 amTimer/counter implementations will all be roughly the same, no matter how you code. Unless, of course, you do something unusual, such as using shift registers for small counters, or writing crazy fast counters to work at 500 MHz.

author: Someone
author_rank: Super Contributor
timestamp: November 08, 2021, 04:17:26 am
content: Quote from: NorthGuy on November 08, 2021, 02:59:56 amYou've probably not looked hard enough at the implementations! Too many people jump straight for their preferred approach rather than check what actually fits best.SRLs already have several possible implementations, but counters are much more diverse (beyond doing trivial exact 2^n factors with a string of T-flops).

author: james_s
author_rank: Super Contributor
timestamp: November 08, 2021, 04:23:58 am
content: Quote from: Cerebus on November 08, 2021, 02:50:29 amI cited practical experience in the very first reply which you apparently ignored. I have been doing FPGA development as a hobby off and on for around 8 years, I have seen no meaningful correlation between lines of code and device utilization. There are numerous different abstraction layers and depending on the type of modeling you're doing you will end up with dramatically more or less lines of code to describe the same circuitry. You could build a counter at the gate level by coding all of the separate gates, or you could build a counter by using a single much higher level instruction. Two very different and perfectly valid techniques, both resulting in exactly the same circuit in the FPGA, with a huge difference in the number of lines of code.

author: SMB784
author_rank: Frequent Contributor
timestamp: November 08, 2021, 04:40:59 am
content: It's simple: in HDL there is no correlation between how many lines of code you write and how much device resources are used.

author: dietert1
author_rank: Super Contributor
timestamp: November 08, 2021, 07:05:43 am
content: Yes, but he wants a confirmation that he and his little ICE40 are doing better than average. That's what i got from all this.I'd go with rstofer: If it does not fit, use a bigger device. "It does not fit" means: Never fill a FPGA more than 50% at development time and don't try to use a CPLD instead, even if you can make the logic just fit. All those projects with this kind of approach developped problems later on, when clients proposed enhancements. The keyword is "sparse": A highway works best when near empty.Regards, Dieter

author: james_s
author_rank: Super Contributor
timestamp: November 08, 2021, 07:08:36 am
content: There are lots of applications for CPLDs where using a FPGA would be like using a sledge hammer to drive a tack. It's always good to leave a bit of space though, if for no other reason than it takes a lot longer to "compile" when the device is heavily utilized.

author: Cerebus
author_rank: Super Contributor
timestamp: November 08, 2021, 01:19:55 pm
content: Quote from: james_s on November 08, 2021, 04:23:58 amSorry James, you did. I'd forgotten that particular contribution, not ignored it. I was just disappointed that more had not used practical experience as a basis to answer the original questions as opposed to answering from abstract point of view.

author: Cerebus
author_rank: Super Contributor
timestamp: November 08, 2021, 01:29:08 pm
content: Quote from: dietert1 on November 08, 2021, 07:05:43 amNo, I don't; no ego or insecurities about the size of my 'device' involved here. There was no need to use the diminutive pejoratively there. I was just explaining what had prompted me to ponder the question.

author: mfro
author_rank: Regular Contributor
timestamp: November 08, 2021, 01:48:36 pm
content: Quote from: Cerebus on November 08, 2021, 01:19:55 pmIf theory already tells that the remote end of the soldering iron is burning hot, I, personally, really don't need the corresponding practical experience

author: Cerebus
author_rank: Super Contributor
timestamp: November 08, 2021, 02:35:08 pm
content: Quote from: mfro on November 08, 2021, 01:48:36 pmA soldering iron is a pretty simple system and is amenable to trivial analysis. Verilog (which I'm guessing is probably Turing Complete) and the infinite number of things one could implement in it isn't a very simple system. Starting from theory it's possible to posit that 1 million lines of Verilog can imply a very simple implementation of just one gate, similarly in theory a line or two of Verilog can imply thousands of gates.However, it's not unreasonable to say that, taking enough examples into account, that the amount of, well and suitably written, Verilog code will scale with the complexity of the problem to be solved and that the implementation in FPGAs, standard cell libraries or their like will also similarly scale. So basic logic would say thereisin the general case a correlation ofsomesort between problem size and the amount of code needed to implement it. That much is obvious if one bothers to think for seven seconds. Whether the correlation is of complexity order O(n), O(n2) or any of the other orders beloved of complexity theorists is a different question entirely. Yes, there are bound to be corner cases like the (1 million lines, 1 gate) and (two lines, a thousand gates) and many less extreme examples but their existence is likely to be in practice, the exception, not the norm.What interested me was whether anyone had seen evidence in practice of this scaling effect to the extent that they'd informally developed an intuition that, in the general case, X lines of code usually leads to Y gates/LCs/whatever-you-want-to-call-them plus or minus some (large) fiddle factor. My Verilog experience extends to perhaps 10 things other than toy examples committed to silicon. I'd describe my level of experience as 'dabbling'. What's needed to properly answer the scaling question is 100s of non-trivial implementations under one's belt.

author: NorthGuy
author_rank: Super Contributor
timestamp: November 08, 2021, 03:17:26 pm
content: Quote from: Someone on November 08, 2021, 04:17:26 amNo. I write my ownsYou can post few examples of diverse timer codings and then we can compare the results, evaluate the resource utilization and draw conclusions for that.

author: SiliconWizard
author_rank: Super Contributor
timestamp: November 08, 2021, 05:52:50 pm
content: Quote from: dietert1 on November 08, 2021, 07:05:43 amIF that's the case, he should just have stated it. Instead of using a convoluted way thinking of an approach (the number of LOCs) that is clearly not appropriate, as he himeself witnessed.As we already said, it's all about the logic structures you're defining. Not the code itself, as there are zillions of ways to express the same functionality. A very short HDL code could be highly inefficient in terms of resource use, while an horribly long one could be very favorable. It's also very hard, for even relatively simple designs - except the most trivial - to anticipate optimizations. We are not machines, thus a given code could yield to very optimized logic with most signals pruned out, for instance.If you want to know whether what you're doing with an HDL is reasonably efficient, you should experiment various approaches for various structures and look at the synthesis result. Most tools can give you a block diagram. That's always an interesting experience. You can also learn from others, although you're likely to find a lot of contradictory approaches and claims. But whatever you do, LOCs are just pretty much meaningless.And with that said, taking what dietert1 said: "are doing better than average", it's even a kind of hopeless quest. Would be the same with software. How can you honestly and objectively determine if a given implementation is doing better than average? It's like a Pandora's box. In software, we can judge algorithms using complexity analysis, but in hardware it's a lot more difficult.If you want to judge your own work in those terms, the only reasonable thing could be to at least take the opposite stance, and ask yourself if you're doing *much worse* than average. That is something that can more or less be determined indeed. But knowing if you're doing better than average is undecidable in general.And finally, code, be it HDL or software, is also a lot about style and readability - not just functionality. You should usually favor a little less "efficient" implementation if it's much easier to read and maintain - as long as it fits your requirements - than trying to implement things in the most efficient way while the end code would be atrocious to make sense of and almost impossible to maintain. Another last thought is about what it is you're trying to evaluate here: in many cases, except again for very simple structures, reaching higher Fmax may lead to higher resource utilization, due to the necessity of duplicating registers, for instance, which tools may do depending on your timing constraints.And, contrary to what you seem to imply, most of us have significant, or even a lot of, experience writing HDL for FPGAs or even ASICs, and this experience backs up what we explained.

author: Cerebus
author_rank: Super Contributor
timestamp: November 08, 2021, 06:09:23 pm
content: Quote from: SiliconWizard on November 08, 2021, 05:52:50 pmAs I've alreadyexplicitlysaid that isnotthe case, it ought to be clear that that strange invention of Dieter's is entirely in his own head, so there's no "IF" involved.

author: asmi
author_rank: Super Contributor
timestamp: November 08, 2021, 07:23:24 pm
content: I never even thought of this, but like with software, a single line of code could be just an simple primitive operation, or a call of subroutine/instantiation of a module, and these two things will obviously consume vastly different amount of resources. Also different FPGA families can have different HW resources (for example LUT4 vs LUT6), and so resource consumption will be different. Finally, there is a retiming and other synthesis/P&R optimizations, which again generate different logic for the same source code.But if you are really curious, you can just pick a bunch of open source HDL projects and run them through synthesis/P&R for a bunch of FPGAs and code analyzer and gather the data you're after.

author: Someone
author_rank: Super Contributor
timestamp: November 08, 2021, 09:18:47 pm
content: Quote from: NorthGuy on November 08, 2021, 03:17:26 pmFrom the user who consistently refuses to contribute actual examples:https://www.eevblog.com/forum/fpga/determine-whether-a-binary-number-is-of-power-of-two-in-verilog-code/?allYeah, keep asking for everyone else to contribute explicit examples when you don't. Keep asking, keep getting the same rebuff. If you won't contribute such an example why should anyone else?Also noting that the exact example of saturating counters has been discussed already:https://www.eevblog.com/forum/fpga/saturating-counters/?allSo your memory is short.Quote from: SiliconWizard on November 08, 2021, 05:52:50 pmSeems like this section of the forum has devolved into another region where the majority are self entitledpeoplehobbyists who reject any sage advice from those of us who are experienced in the real world. Perhaps time to start actively not-participating rather than wasting time.

author: james_s
author_rank: Super Contributor
timestamp: November 08, 2021, 09:52:28 pm
content: This really seems like a case of trying to compare two arbitrary metrics and look for correlation. The thing about HDL is it is not code in a traditional sense, it is not instructions being executed, it is a description of a circuit. The thing about descriptions is that there are so many ways one can describe the same thing that you could end up with hundreds of pages or just a few sentences, both accurately describing the same thing. For example if you want to describe a cube drawn on a piece of paper you could just say there's a cube drawn on a piece of paper of this size originating at whatever coordinates, or you could say there's a line drawn from this point to that point and another line drawn from another set of coordinates and so on. Both are perfectly valid methods of describing the drawing but from different abstraction layers with vastly different length of description. There are many, many different ways of describing the same circuit, and there is not always one correct way.Lines of code in general is not a very useful metric, but is even less meaningful with HDL than with a procedural languages.

author: NorthGuy
author_rank: Super Contributor
timestamp: November 08, 2021, 10:28:58 pm
content: Quote from: Someone on November 08, 2021, 09:18:47 pmHehe. I did provide lots of examples. I described them in English, which is an appropriate language when talking to humans. The hardware I described would not change if it was described in Verilog, VHDL, Chisel or whatnot. The hardware design exists regardless of how it is described, regardless of the language, and regardless of the coding style. You can even get logic ICs and build your design without ever describing it at all.That's the same as an engineer designing a bridge. The bridge is the same whether the engineer prepared blueprints, CAD files, plain text instructions how to build the bridge, or whatever else which contains enough information to build the bridge. You wouldn't care then if the size of the bridge is correlated with the size of the CAD files, would you?