Author Topic: work around VHDL's lack of a preprocessor  (Read 6174 times)

0 Members and 1 Guest are viewing this topic.

Offline Bassman59Topic starter

  • Super Contributor
  • ***
  • Posts: 2501
  • Country: us
  • Yes, I do this for a living
work around VHDL's lack of a preprocessor
« on: September 23, 2021, 12:04:21 am »
In all of my years doing VHDL I've never needed a preprocessor. Until now.

I am working on a command parser that is meant to be used on a number of design variants. For the most part, the commands set (and get) parameters. Each variant implements most of the commands, but there are a handful of things used by one variant which don't exist in the others. The command space is 256 possible entries, of which most are not implemented.

Something higher up provides a command token along with an argument. After parsing the command, a response is sent to the higher up.

All of the various parameters are wrapped up into a nice record type. This makes the entity's port list manageable, and it also makes it straightforward to have variant-specific parameter lists: just define the record type with the parameters needed. There is no need to change the parser entity port list.

The command parser boils down to a big case statement, with the command token as the selector. Any commands not implemented fall through the "when others" and the response to higher up indicates "not implemented."

Here's the rub. Like I said, each variant has some special commands which don't exist in the other variants. It Would Be Nice if there was a C-style pre-processor which can exclude certain lines from analysis. VHDL-2008 does not have such a feature. (The good news is that it has been added to VHDL-2019, but I expect to be well into retirement by the time the tools support it.)

Is there a "good" way of excluding, at compile time, individual "when" entries in the case statement? The reason is that if a parameter is not defined for a variant, then it's not in the record type and you can't have it appear at all in the "when" section. Some code:

Code: [Select]
Decoder : case token is
    when CMD_XYZ =>
        -- VARIANT is a generic:
        if VARIANT = THIS_ONE then
            -- XYZ is in the THIS_ONE version of the params record, but not in any other
            params.XYZ <= argument;
            response <= HANDLED;
        else
            response <= NOT_IMPLEMENTED;
        end if;

    when others =>
        response <= NOT_IMPLEMENTED;

In CMD_XYZ the analyzer will always consider both the true and the false conditions, so even if VARIANT is not THIS_ONE, the analyzer expects params.XYZ to be defined. Like I said, a pre-processor is the simple solution.

I suppose the workarounds are:

1. Have an architecture for each variant, which is selected in the usual way at instantiation of the entity, or
 
2. Write what I did in the example, and actually include all of the possible parameters even if not used, and assume the synthesizer will optimize away the actual assignments to the unused parameters. Remember VARIANT is a generic and THIS_ONE is a constant.

There's an added complication: all of these parameters get written to non-volatile storage and that's a somewhat precious resource and I'd rather not waste space in it for parameters that are not used.

Please don't say "Use SystemVerilog" even if that language has such support!

Hope this is clear enough and makes sense ...
 

Offline Someone

  • Super Contributor
  • ***
  • Posts: 4525
  • Country: au
    • send complaints here
Re: work around VHDL's lack of a preprocessor
« Reply #1 on: September 23, 2021, 04:24:49 am »
What you described (propagating a constant to prune conditionals/states) works ok, by wrapping it in if's at that level makes it clearer to the tools. Messy code but gets the job done.

An alternative would be to make the tools realise some of the literals of the enum aren't possible on the case expression (state machines are pruned/optimised like this). A function in the package declaring the enum that takes all the possible inputs and translates it to the set implemented in that variant?
 

Offline AaronLee

  • Regular Contributor
  • *
  • Posts: 229
  • Country: kr
Re: work around VHDL's lack of a preprocessor
« Reply #2 on: September 23, 2021, 05:51:52 am »
Coming from the world of programming in C and other languages, VHDL is in desperate need of a preprocessor in my opinion. In C, you can, for example, comment out a section of code with '/*' and '*/'. Or you can define macros to conditionally enable/disable sections of code. I found from day one of learning VHDL how inadequate it is without a preprocessor, but have no choice when the company/customer require it to be written in VHDL. Perhaps someone has written a preprocessor for VHDL to do those things, but unfortunately even if it existed, it's likely not integrated with the development environment, nor is standard VHDL (before the preprocessor) and to which the company/customer would likely complain being it wouldn't be readable by other engineers.
 

Offline Just_another_Dave

  • Regular Contributor
  • *
  • Posts: 192
  • Country: es
Re: work around VHDL's lack of a preprocessor
« Reply #3 on: September 23, 2021, 07:15:12 am »
There is a project called vhdlpp which allows to configure VHDL code before  synthesizing it. Itseems quite similar to cppmake: http://vhdlpp.sourceforge.net/README

Nevertheless, generics are normally the recommended way of achieving that, as they avoid problems that copypasting a macro could cause
 
The following users thanked this post: paf

Offline brucehoult

  • Super Contributor
  • ***
  • Posts: 4028
  • Country: nz
Re: work around VHDL's lack of a preprocessor
« Reply #4 on: September 23, 2021, 08:21:56 am »
What's wrong with just having your build system run the actual C preprocessor?
 
The following users thanked this post: paf

Offline paf

  • Regular Contributor
  • *
  • Posts: 91
Re: work around VHDL's lack of a preprocessor
« Reply #5 on: September 23, 2021, 09:31:12 am »
From the  web page: 
VHDLproc is a simple command line VHDL preprocessor written in Python following the conditional compilation directives outlined in VHDL-2019, with a few extensions.
https://github.com/nobodywasishere/VHDLproc

So, this may give you the macro extensions of VHDL-2019, without VHDL-2019. Disclaimer: I have not tried it.

Other suggestions may be valid or not, depending on the languages you may already know, like or want to know more.

M4  -- is present on all Unix machines, and is useful for other things. 
https://www.gnu.org/software/m4/manual/index.html
https://mbreen.com/m4.html


In TCL you have these two preprocessors:

G2
http://users.telenet.be/koen.vandamme1/c_tools/g2/_index.htm
Expand
https://wiki.tcl-lang.org/page/expand

I have used the first, to pre-process Verilog.

Jinja  -- in Python 
https://jinja.palletsprojects.com/en/3.0.x/

Free Marker -- in Java
https://freemarker.apache.org

You have lots of choices.

 
The following users thanked this post: Just_another_Dave

Offline Bassman59Topic starter

  • Super Contributor
  • ***
  • Posts: 2501
  • Country: us
  • Yes, I do this for a living
Re: work around VHDL's lack of a preprocessor
« Reply #6 on: September 23, 2021, 02:54:36 pm »
Coming from the world of programming in C and other languages, VHDL is in desperate need of a preprocessor in my opinion. In C, you can, for example, comment out a section of code with '/*' and '*/'. Or you can define macros to conditionally enable/disable sections of code. I found from day one of learning VHDL how inadequate it is without a preprocessor, but have no choice when the company/customer require it to be written in VHDL. Perhaps someone has written a preprocessor for VHDL to do those things, but unfortunately even if it existed, it's likely not integrated with the development environment, nor is standard VHDL (before the preprocessor) and to which the company/customer would likely complain being it wouldn't be readable by other engineers.

C-style block comments /* */ are actually already included in VHDL-2008 -- see LRM section 15.9. It's easy enough to select a block of code and do C-c C-c in emacs, though. But that doesn't solve my problem, which is to be able to include or exclude blocks of code within a process at analysis time.

For my purposes, my company has no particular style requirements, so I can use whatever I want, as long as I document what I'm doing. (Mainly so I remember what the hell I did.)
 

Offline Bassman59Topic starter

  • Super Contributor
  • ***
  • Posts: 2501
  • Country: us
  • Yes, I do this for a living
Re: work around VHDL's lack of a preprocessor
« Reply #7 on: September 23, 2021, 02:57:07 pm »
What's wrong with just having your build system run the actual C preprocessor?

To be honest, I hadn't thought about that, although the build environment is basically the vendor tools.
 

Offline Bassman59Topic starter

  • Super Contributor
  • ***
  • Posts: 2501
  • Country: us
  • Yes, I do this for a living
Re: work around VHDL's lack of a preprocessor
« Reply #8 on: September 23, 2021, 03:03:00 pm »
There is a project called vhdlpp which allows to configure VHDL code before  synthesizing it. Itseems quite similar to cppmake: http://vhdlpp.sourceforge.net/README

Nevertheless, generics are normally the recommended way of achieving that, as they avoid problems that copypasting a macro could cause

That "preprocessor" seems to be just a way to cleverly comment-out code.

Generics should drive the process (not the VHDL process) of determining what gets included and excluded. But the usual way of doing that is to have generate statements which use the generics, and that works well for things like replicating entity instances and blocks of code, all sorts of things. But generates don't work within a process.
 

Offline Bassman59Topic starter

  • Super Contributor
  • ***
  • Posts: 2501
  • Country: us
  • Yes, I do this for a living
Re: work around VHDL's lack of a preprocessor
« Reply #9 on: September 23, 2021, 03:08:18 pm »
From the  web page: 
VHDLproc is a simple command line VHDL preprocessor written in Python following the conditional compilation directives outlined in VHDL-2019, with a few extensions.
https://github.com/nobodywasishere/VHDLproc

So, this may give you the macro extensions of VHDL-2019, without VHDL-2019. Disclaimer: I have not tried it.

Oh, wow, that looks like it might be the ticket! I'll play with it and report back. This is especially interesting because it won't require any source code changes once the tool vendors finally decide to support VHDL-2019 (in like 20 years).

Quote
Other suggestions may be valid or not, depending on the languages you may already know, like or want to know more.

M4  -- is present on all Unix machines, and is useful for other things. 
https://www.gnu.org/software/m4/manual/index.html
https://mbreen.com/m4.html

My first and last time looking at M4 macros was a zillion years ago when I looked (very briefly) at possibly using gEDA for schematics and PCB layout. I think they used M4 macros to define footprints. I cannot imagine a less user-friendly way to do that.

gEDA was such a disaster and the developers were so openly hostile to suggestions that I ignored it. Anyway.

Quote
In TCL you have these two preprocessors:

G2
http://users.telenet.be/koen.vandamme1/c_tools/g2/_index.htm
Expand
https://wiki.tcl-lang.org/page/expand

I have used the first, to pre-process Verilog.

Jinja  -- in Python 
https://jinja.palletsprojects.com/en/3.0.x/

Free Marker -- in Java
https://freemarker.apache.org

You have lots of choices.

I'll look at those, thanks.
 

Offline Bassman59Topic starter

  • Super Contributor
  • ***
  • Posts: 2501
  • Country: us
  • Yes, I do this for a living
Re: work around VHDL's lack of a preprocessor
« Reply #10 on: September 23, 2021, 03:50:17 pm »
What you described (propagating a constant to prune conditionals/states) works ok, by wrapping it in if's at that level makes it clearer to the tools. Messy code but gets the job done.

An alternative would be to make the tools realise some of the literals of the enum aren't possible on the case expression (state machines are pruned/optimised like this). A function in the package declaring the enum that takes all the possible inputs and translates it to the set implemented in that variant?

I'm not sure what that function is supposed to do?

Remember the thing is a command decoder, and each command basically updates signals used elsewhere in the design. By this I mean: the TRIGGER command asserts a trigger strobe to the data-capture machine. The SET_TEMPERATURE command loads a DAC used as a temperature set-point. The rub is that for example SET_PARAMETER_FOO, which updates a parameter called FOO, exists only in variant A, not in B, C or D.

After thinking about this overnight, if I can't get that VHDL-2019 pre-processor Python thing to work, I will just bite the bullet and declare the parameter record to hold all parameters that exist in all variants, and then use a generic to gate on commands which exist in a given variant. After the synthesizer gets through with the code, the unused stuff will get optimized away, with a host of red warnings in the report. The memory map for the parameters in the non-volatile storage will have some holes in it for one variant or another (the map itself is the same for all variants), but that's fine. It's not like I have a thousand parameters to manage.
 

Offline SiliconWizard

  • Super Contributor
  • ***
  • Posts: 14445
  • Country: fr
Re: work around VHDL's lack of a preprocessor
« Reply #11 on: September 23, 2021, 05:06:55 pm »
Yes, the only way of doing this in VHDL is to use "if" statements as you did.
When the "if" clause is known at compile-time and is false, the corresponding code will just get pruned. Likewise, any signal (including record members) that is not used in a design will get pruned. So this is the exact equivalent of a preprocessor.

What would  a preprocessor bring here?
One thing to realize is that many features of VHDL, when they can be evaluated at compile-time, are actually equivalent to preprocessing - just much better.
« Last Edit: September 23, 2021, 05:18:43 pm by SiliconWizard »
 

Offline blacksheeplogic

  • Frequent Contributor
  • **
  • Posts: 532
  • Country: nz
Re: work around VHDL's lack of a preprocessor
« Reply #12 on: September 23, 2021, 09:43:08 pm »
What's wrong with just having your build system run the actual C preprocessor?

It's really going to depend on what you are allowed to get away with changing:

I've done this in the past when I have needed a pre-processor, for example an assembler that did not support include files. I've also needed to write my own pre-processors which are typically very simple programs. But you also need to either modify a default build rule which I don't like doing or add a build rule + dependency to the makefile which may also require modifying the dependency generator and if you are using a source editor with syntax support you may need to modify your editors config as well. On large projects it may not be possible to change the build procedures and at least the build teams I have worked with could best be described as change adverse. I've checked in the processed source files and just kept the custom build tools within the team in these cases.

It can also piss off other developers when you change the build tools especially if you change a tool for example create your own make. Don't expect other developers to ever read readme.txt.
 

Offline Someone

  • Super Contributor
  • ***
  • Posts: 4525
  • Country: au
    • send complaints here
Re: work around VHDL's lack of a preprocessor
« Reply #13 on: September 23, 2021, 10:49:03 pm »
Generics should drive the process (not the VHDL process) of determining what gets included and excluded.
You might be limiting your scope/applications of generics thinking of them this way. They are a fancy constant, that can be set at compile time to differentiate the entity from other instantiations (be that within the same project, or between projects, or at different times, etc, etc).

What you described (propagating a constant to prune conditionals/states) works ok, by wrapping it in if's at that level makes it clearer to the tools. Messy code but gets the job done.

An alternative would be to make the tools realise some of the literals of the enum aren't possible on the case expression (state machines are pruned/optimised like this). A function in the package declaring the enum that takes all the possible inputs and translates it to the set implemented in that variant?
I'm not sure what that function is supposed to do?
You need a function/assignment/process that the tools recognise will only ever have a subset of the "states" of the enum coming out of them. Think of it as the next step after constant propagation, set reduction/pruning. I've not tested this for the general sense, but the major tools are certainly doing this for state machines (particularly when spread across multiple processes). They know which states are unused in a case select and optimise them out automatically.
 

Offline Bassman59Topic starter

  • Super Contributor
  • ***
  • Posts: 2501
  • Country: us
  • Yes, I do this for a living
Re: work around VHDL's lack of a preprocessor
« Reply #14 on: September 24, 2021, 02:10:51 am »
Generics should drive the process (not the VHDL process) of determining what gets included and excluded.
You might be limiting your scope/applications of generics thinking of them this way. They are a fancy constant, that can be set at compile time to differentiate the entity from other instantiations (be that within the same project, or between projects, or at different times, etc, etc).

Oh, believe me, I love to use generics for many things. I use them for setting part revisions and beta build constants (as read back over some communications link). I use them to set clock division ratios for, say, an SPI peripheral. If it's a constant that I might want to override, I make it a generic!

Quote
What you described (propagating a constant to prune conditionals/states) works ok, by wrapping it in if's at that level makes it clearer to the tools. Messy code but gets the job done.

An alternative would be to make the tools realise some of the literals of the enum aren't possible on the case expression (state machines are pruned/optimised like this). A function in the package declaring the enum that takes all the possible inputs and translates it to the set implemented in that variant?
I'm not sure what that function is supposed to do?
You need a function/assignment/process that the tools recognise will only ever have a subset of the "states" of the enum coming out of them. Think of it as the next step after constant propagation, set reduction/pruning. I've not tested this for the general sense, but the major tools are certainly doing this for state machines (particularly when spread across multiple processes). They know which states are unused in a case select and optimise them out automatically.

Ohhh, wait, I think I am getting the idea!

Let's begin with my command parser description. I create an enumeration that defines all possible command tokens for all design variants. A signal of that type is the case expression. (Just like a state machine.) Each entry in the enumeration is a selector in the case statement. Each selector drives some signals. This case statement therefore covers all possible design variants.

Even if a particular variant will never get some of the defined commands (this is guaranteed because I control both sides of the command-sending pipe), the selectors for the commands will still exist. Now if there is nothing connected to those signals (this is in the variant-specific code), then we might assume that the tools will recognize this and work backwards and ultimately optimize away the case selector.

But the problem is that in the system, every command sent to the FPGA gets a response back. Unimplemented and undefined commands get a response that says, "not supported!" (Again, because I control both ends of the communications, undefined commands are never sent ... but we should be prudent and define what happens when such an event occurs.)

It is because of the requirement that a response is returned that I have to work out what happens if the unimplemented for this variant command is mistakenly sent.

So then what is needed is a "prescreener" function: the input is the command token. The function has a variant-specific mechanism (lookup table?) that replaces unsupported commands with a default "not implemented" command. If the command is supported, the output is the input command. This lookup is all a ROM made at compile time. The output of this function is used as the case expression. (I think VHDL-2008 even allows for the function call to be part of the case expression; if not, whatever, I'll make an intermediate signal.)

Aside: I think I can use a package generic to choose which variant's lookup table is used in that function. The function will be in the same package.

Will it result in the unpossible command selectors being optimized away? There's only one way to find out: code it and synthesize it, which will be project for tomorrow.
 
The following users thanked this post: Someone

Offline SiliconWizard

  • Super Contributor
  • ***
  • Posts: 14445
  • Country: fr
Re: work around VHDL's lack of a preprocessor
« Reply #15 on: September 24, 2021, 07:42:12 pm »
In synthesizable code, functions and procedures in VHDL can only be evaluated at compile time - thus when properly used, they give fancy preprocessing features.

Then, outside of processes, you can use 'generate' blocks. (if generate / for generate). They also give you the equivalent of a conventional preprocessor. You can't use them inside a process though, so in this context, you can use 'if' statements as I said above - if the clause is known at compile time, this will be equivalent to preprocessing - and also functions and procedures.

With all this, I actually almost never see a need for an additional preprocessor.
 
The following users thanked this post: nctnico

Offline nctnico

  • Super Contributor
  • ***
  • Posts: 26892
  • Country: nl
    • NCT Developments
Re: work around VHDL's lack of a preprocessor
« Reply #16 on: September 24, 2021, 11:19:39 pm »
The 'generate' statement is the way to get this kind of things done.

Using the 'if' statement is just as messy as littering C code with #ifdefs. It doesn't result in code that is very maintanable so some restructuring needs to be done to have a better isolation between the variants. Perhaps using an array with initialised value pairs that defines the behaviour of each while using generic code is a way to deal with the problem.
« Last Edit: September 24, 2021, 11:23:06 pm by nctnico »
There are small lies, big lies and then there is what is on the screen of your oscilloscope.
 

Offline Someone

  • Super Contributor
  • ***
  • Posts: 4525
  • Country: au
    • send complaints here
Re: work around VHDL's lack of a preprocessor
« Reply #17 on: September 25, 2021, 02:11:58 am »
In synthesizable code, functions and procedures in VHDL can only be evaluated at compile time - thus when properly used, they give fancy preprocessing features.
That might be a bad use of the term "evaluated", since both functions and processes are synthesiseable and used to produce complex combinatorial results (the majority of ieee packages are functions alongside operator overrides which are functions themselves). So they are most certainly evaluated at runtime.

Things that are only evaluated at compile time are called static.

The 'generate' statement is the way to get this kind of things done.
Except generate is restricted in scope, so cant be placed inside the case select. At which point the OP would be replicating/cut/pasting the different variants of their case select into different generate clauses (no else on generate!). Its absolutely the wrong way to do it, the if statements with constants to gate them is much more maintainable/readable since the common parts are repeated in separate lines. Perhaps you could provide an example following the OPs excellent post with their sample code....
 

Offline SiliconWizard

  • Super Contributor
  • ***
  • Posts: 14445
  • Country: fr
Re: work around VHDL's lack of a preprocessor
« Reply #18 on: September 25, 2021, 05:15:07 pm »
In synthesizable code, functions and procedures in VHDL can only be evaluated at compile time - thus when properly used, they give fancy preprocessing features.
That might be a bad use of the term "evaluated", since both functions and processes are synthesiseable and used to produce complex combinatorial results (the majority of ieee packages are functions alongside operator overrides which are functions themselves). So they are most certainly evaluated at runtime.

Nope nope. This was a carefully choosen term here.

You show a misconception of what functions and procedures are in VHDL, or you just didn't understand or even read what I wrote. When synthesized, they can ONLY be evaluated at compile-time. They always yield static logic structures that reflect their behavior. That's why, for synthesis, they act as preprocessing and nothing else.

But reading your paragraph, I'm pretty sure you didn't understand what I said and just took it as a way of saying functions and procedures have no use for synthesis, which is pretty much the opposite of what I said.

They are indeed "evaluated" at compile-time for synthesis. Only for simulation they can be evaluated during run-time. Evaluated at compile-time for synthesis means: they yield static logic at compile-time. Always. That didn't mean they can't take signals as inputs, for instance. Yeah, re-reading what you said convinces me you thought I meant that they could only be used with constants, and not signals or variables.

Thus, for synthesis, they can be seen as templates. This is the closest parallel I can think of with software.
Once you understand this, what is synthesizable and what isn't when using functions and procedures becomes almost obvious.
 
The following users thanked this post: nctnico

Offline nctnico

  • Super Contributor
  • ***
  • Posts: 26892
  • Country: nl
    • NCT Developments
Re: work around VHDL's lack of a preprocessor
« Reply #19 on: September 25, 2021, 06:14:23 pm »
The 'generate' statement is the way to get this kind of things done.
Except generate is restricted in scope, so cant be placed inside the case select. At which point the OP would be replicating/cut/pasting the different variants of their case select into different generate clauses (no else on generate!). Its absolutely the wrong way to do it, the if statements with constants to gate them is much more maintainable/readable since the common parts are repeated in separate lines. Perhaps you could provide an example following the OPs excellent post with their sample code....
I already wrote that in the part you snipped: use table driven case statements to make functionality optional without littering the code with ifs. But the OP's example is probably just an example. And you don't need to make things complicated or replicate code; just think & do research a bit longer about how to structure code to suit the problem the best instead of getting behind the keyboard and start writing code into a dead end street. Maybe -as SiliconWizard wrote- functions and procedures can also help to un-spaghetti the code.
« Last Edit: September 25, 2021, 06:42:35 pm by nctnico »
There are small lies, big lies and then there is what is on the screen of your oscilloscope.
 

Offline asmi

  • Super Contributor
  • ***
  • Posts: 2730
  • Country: ca
Re: work around VHDL's lack of a preprocessor
« Reply #20 on: September 25, 2021, 07:11:44 pm »
LOL you guys as always went deep into the woods in your attempts to defend that POS of a language :palm: As I understood, what OP wants is this (code in C so that even VHDLers would understand):
Code: [Select]
switch (op)
{
case OP_FOO:
//handing operation FOO
break;
case OP_BAR:
//handing operation BAR
break;
#ifdef OP_EXTENDED_1_SUPPORTED
case OP_EXTENDED_1:
//handing operation OP_EXTENDED_1
break;
#endif
#ifdef OP_EXTENDED_2_SUPPORTED
case OP_EXTENDED_2:
//handing operation OP_EXTENDED_2
break;
#endif
default:
//handing unknown operation
break;
}
Important point is that OP_EXTENDED_x opcodes are treated as unknown ones if such support is disabled. Now please show us how to implement this trivial code. And no, a bunch of generate's with copy-pasted switched for all possible permutations of supported opcodes is not acceptable.

So yes, "use SystemVerilog" is the only sureway solution to avoid having to deal with this garbage again.
 
The following users thanked this post: Someone

Offline nctnico

  • Super Contributor
  • ***
  • Posts: 26892
  • Country: nl
    • NCT Developments
Re: work around VHDL's lack of a preprocessor
« Reply #21 on: September 25, 2021, 07:25:45 pm »
One way: make a component for the body of each case statement. That component's contents can have a generate statement that creates output based on what is being generated. There is zero code replication. In fact, closely related functions can be implemented using the same component.
There are small lies, big lies and then there is what is on the screen of your oscilloscope.
 

Offline asmi

  • Super Contributor
  • ***
  • Posts: 2730
  • Country: ca
Re: work around VHDL's lack of a preprocessor
« Reply #22 on: September 25, 2021, 07:40:38 pm »
Enough talk, show us the code already! The C code I've posed above can be transferred into SystemVerilog pretty much in exact same form with no trickery required, so please show us how to achieve the same thing in VHDL.

Offline SiliconWizard

  • Super Contributor
  • ***
  • Posts: 14445
  • Country: fr
Re: work around VHDL's lack of a preprocessor
« Reply #23 on: September 25, 2021, 08:13:51 pm »
One way: make a component for the body of each case statement. That component's contents can have a generate statement that creates output based on what is being generated. There is zero code replication. In fact, closely related functions can be implemented using the same component.

Why not, but this would be unnecessarily heavy.

Again, just using "if" with a constant clause is guaranteed to be optimized. This is one of the most basic optimizations possible. No need to question that.
 

Offline nctnico

  • Super Contributor
  • ***
  • Posts: 26892
  • Country: nl
    • NCT Developments
Re: work around VHDL's lack of a preprocessor
« Reply #24 on: September 25, 2021, 08:28:38 pm »
Enough talk, show us the code already! The C code I've posed above can be transferred into SystemVerilog pretty much in exact same form with no trickery required, so please show us how to achieve the same thing in VHDL.
Actually you can but you'd use a plain if instead of #ifdef. You basically insist on using #ifdef while there is a VHDL language construct (namely the 'if statement') that does exactly the same from a functional point of view when the condition is based on a constant. The OP's question however seems to be how to create nicer looking code that isn't littered with a whole bunch of ifs and #ifdef doesn't make things any nicer. Take note of SiliconWizzards remark about how and why a synthesizer is already doing the same as the C pre-processor. VHDL code that is never used, is optimised away so why insist on adding an extra layer to the language that does the same?
« Last Edit: September 25, 2021, 08:33:59 pm by nctnico »
There are small lies, big lies and then there is what is on the screen of your oscilloscope.
 

Offline SiliconWizard

  • Super Contributor
  • ***
  • Posts: 14445
  • Country: fr
Re: work around VHDL's lack of a preprocessor
« Reply #25 on: September 25, 2021, 09:09:51 pm »
But yes, if the point is making the code look "cleaner" with fewer if's, then you can structure your code differently. Not sure going through hoops is worth it for the example the OP gave though.

But sometimes you have groups of 'when' clauses depending on a given contant/generic inside a 'case' statement, and using a 'if' for each is clunky. Grouping would look tidier (and probably less error-prone).

I sometimes do that by splitting a 'case' into several 'case', each guarded by an 'if'. With the VHDL rule for a sequence of statements, this works fine.
Such as, taking the OP's example:

Code: [Select]
response <= NOT_IMPLEMENTED;

if VARIANT = THIS_ONE then
    Decoder_THISONE : case token is
        when CMD_XYZ =>
            params.XYZ <= argument;
            response <= HANDLED;
       
        when ... =>
        ...
        when others =>
    end case;
end if;

if VARIANT = OTHER_ONE then
    Decoder_OTHER_ONE  : case token is
        when CMD_SOMETHING =>
            ...
            response <= HANDLED;

        when ... =>
        ...
        when others =>
    end case;
end if;

You get the idea.
« Last Edit: September 25, 2021, 09:11:40 pm by SiliconWizard »
 
The following users thanked this post: nctnico

Offline asmi

  • Super Contributor
  • ***
  • Posts: 2730
  • Country: ca
Re: work around VHDL's lack of a preprocessor
« Reply #26 on: September 25, 2021, 10:54:32 pm »
Actually you can but you'd use a plain if instead of #ifdef. You basically insist on using #ifdef while there is a VHDL language construct (namely the 'if statement') that does exactly the same from a functional point of view when the condition is based on a constant. The OP's question however seems to be how to create nicer looking code that isn't littered with a whole bunch of ifs and #ifdef doesn't make things any nicer. Take note of SiliconWizzards remark about how and why a synthesizer is already doing the same as the C pre-processor. VHDL code that is never used, is optimised away so why insist on adding an extra layer to the language that does the same?
That's more talking, while I still don't see the code. Please show us the version of a code for my example above. Remember, there are four possible cases as each of EXTENDED_OPs can be enabled or disabled independently. This is a quite common use case, so there's got to be a way to make it happen.
 
The following users thanked this post: Someone

Offline Someone

  • Super Contributor
  • ***
  • Posts: 4525
  • Country: au
    • send complaints here
Re: work around VHDL's lack of a preprocessor
« Reply #27 on: September 26, 2021, 12:36:27 am »
In synthesizable code, functions and procedures in VHDL can only be evaluated at compile time - thus when properly used, they give fancy preprocessing features.
That might be a bad use of the term "evaluated", since both functions and processes are synthesiseable and used to produce complex combinatorial results (the majority of ieee packages are functions alongside operator overrides which are functions themselves). So they are most certainly evaluated at runtime.
Nope nope. This was a carefully choosen term here.

You show a misconception of what functions and procedures are in VHDL, or you just didn't understand or even read what I wrote. When synthesized, they can ONLY be evaluated at compile-time. They always yield static logic structures that reflect their behavior. That's why, for synthesis, they act as preprocessing and nothing else.
Static is a strictly defined term in VHDL (the language) so you cant just redefine and reuse it how you like. Evaluated is not strictly defined but most people would understand it to mean the inputs are parsed to produce the output. Elaboration is probably where you were headed, but your refining/misunderstanding of terms makes your contributions incoherent.
 

Offline SiliconWizard

  • Super Contributor
  • ***
  • Posts: 14445
  • Country: fr
Re: work around VHDL's lack of a preprocessor
« Reply #28 on: September 26, 2021, 01:57:47 am »
Static is a strictly defined term in VHDL (the language) so you cant just redefine and reuse it how you like. Evaluated is not strictly defined but most people would understand it to mean the inputs are parsed to produce the output. Elaboration is probably where you were headed, but your refining/misunderstanding of terms makes your contributions incoherent.

Let's not uselessly pollute this thread please.
I'll just reply to this: 1/ that my use of 'static' here was strictly in "static logic structure", which had nothing to do with the "static expressions" which is the only thing defined in the VHDL standard related to the word 'static'. One may object that 'static' here would be sort of redundant, as synthesis tools can only generate a static logic structure anyway. Static as in fixed. 2/ That if anything, the term of "compilation" I used could have been questioned, as it's not how the VHDL standard defines how VHDL input is processed - it talks about analysis and elaboration. But almost anyone using HDL routinely talks about "compilation", including tools vendors. Then whether it actually happens during analysis or elaboration, probably nobody cares here, unless you're writing VHDL tools. Point is, again, (was it really not clear?) that functions and procedures in the context of synthesis are nothing but fancy preprocessing - which was the whole point all along.
 

Offline BrianHG

  • Super Contributor
  • ***
  • Posts: 7726
  • Country: ca
Re: work around VHDL's lack of a preprocessor
« Reply #29 on: September 26, 2021, 02:26:16 am »
@Bassman59, have you test compiled placing an 'IF (option_parameter)' inside the optional cases VS selecting 2 groups of functions?

I know in SV, when test compiling two similar scenarios, as long as it is a parameter or fixed value, the compiler prunes out the unused logic and ends up generating A or B as if I wrote out a single selected case group.

The other option is a 2 dimensional case, the outer being the 'option_parameter' and the compiler still simplifies/prunes down the logic to A or B.  The case where this simplification doesn't happen is if the 'option_parameter' is a variable logic input instead of a parameter constant, or hard wired high or low.
 

Offline Someone

  • Super Contributor
  • ***
  • Posts: 4525
  • Country: au
    • send complaints here
Re: work around VHDL's lack of a preprocessor
« Reply #30 on: September 26, 2021, 02:52:32 am »
Let's not uselessly pollute this thread please.
[barely coherent waffle]
Point is, again, (was it really not clear?) that functions and procedures in the context of synthesis are nothing but fancy preprocessing - which was the whole point all along.
Functions are functions as defined by the language, their implementation is important to keep in mind but its much clearer in VHDL than in some other languages. In VHDL functions are evaluated at execution ("runtime") and not limited to evaluation at compile time.

Restricting the design at compile time is one of the significant differences in HDL design vs normal software development, as the FPGA resources are typically scarce/precious. You keep flaming your poor communication:
In synthesizable code, functions and procedures in VHDL can only be evaluated at compile time - thus when properly used, they give fancy preprocessing features.
No, functions are still able to be evaluated/executed after compilation. You said only, I left you ample room to be gracious, but you just dig in.
 

Offline Someone

  • Super Contributor
  • ***
  • Posts: 4525
  • Country: au
    • send complaints here
Re: work around VHDL's lack of a preprocessor
« Reply #31 on: September 26, 2021, 03:15:44 am »
Will it result in the unpossible command selectors being optimized away? There's only one way to find out: code it and synthesize it, which will be project for tomorrow.
Cant wait to hear the result! Since you are chasing that implementation concept, I took another to test out:

Quote

type VARIANT_TYPE is (E_ALL,E_VAR1,E_VAR2,E_TEST);
constant THIS_VARIANT : VARIANT_TYPE := E_VAR2;

type STATE_TYPE is (S_BLEEP,S_BLOOP,S_NUREEK,S_HERUNGER,S_ROATUT,S_UNIMPLEMENTED);
signal command : STATE_TYPE;

constant VARIANT_WIDTH : INTEGER := integer(ceil(log2(real(VARIANT_TYPE'pos(VARIANT_TYPE'high)+1))));
constant STATE_WIDTH   : INTEGER := integer(ceil(log2(real(  STATE_TYPE'pos(  STATE_TYPE'high)+1))));

function state_encode(
  variant : in VARIANT_TYPE;
  state   : in STATE_TYPE)
  return STD_LOGIC_VECTOR is
  variable encoded : STD_LOGIC_VECTOR (VARIANT_WIDTH+STATE_WIDTH-1 downto 0);
begin
  encoded := std_logic_vector(to_unsigned(VARIANT_TYPE'pos(variant), VARIANT_WIDTH) & to_unsigned(STATE_TYPE'pos(state), STATE_WIDTH));
  if variant = E_ALL then
    encoded(encoded'high downto encoded'high+1-VARIANT_WIDTH) := (others => '-');
  end if;
  return encoded;
end function;

begin

process(all)
begin
if rising_edge(clock) then
  case state_encode(THIS_VARIANT,command) is
    when state_encode(E_ALL,S_BLEEP) =>
      params.bleep  <= arguement;
      response      <= R_OK;
    when state_encode(E_VAR1,S_BLOOP) |
         state_encode(E_VAR2,S_BLOOP) =>
      params.bloop  <= arguement;
      response      <= R_OK;
    when state_encode(E_VAR1,S_NUREEK) =>
      params.nureek <= arguement;
      response      <= R_OK;
    when state_encode(E_VAR1,S_ROATUT) =>
      params.roatut <= arguement;
      response      <= R_OK;
    when state_encode(E_TEST,S_HERUNGER) =>
      response      <= R_OK;
    when others =>
      response      <= R_UNIMPLEMENTED;
  end case;
end if;
end process;
(get stuffed scrolling "code" box)

The if in the function is a little inelegant with its verbose range indexing, but the optimization rips through it and does what you were asking for in the original post. Most of the declaration above can be pushed back into a suitable package and it ends up quite nice to use.
 

Offline nctnico

  • Super Contributor
  • ***
  • Posts: 26892
  • Country: nl
    • NCT Developments
Re: work around VHDL's lack of a preprocessor
« Reply #32 on: September 26, 2021, 11:14:42 am »
The problem the OP has is a code structuring one. First thing that needs to be done is for the command handling part to always support all commands (so the enumeration needs to be complete with all commands). Secondly a layer (translation table, function, whatever) needs to go between the input and command processing. That layer uses the variant type to check if a certain command is supported or not. This likely takes some restructuring of the code but that advantage is that determining which commands are supported by what type is in 1 location. This will help to keep code maintainable.

@Someone: it is better when your function returns an enumeration. Then the synthesizer can decide what kind of encoding is the most efficient.
« Last Edit: September 26, 2021, 11:18:07 am by nctnico »
There are small lies, big lies and then there is what is on the screen of your oscilloscope.
 

Offline asmi

  • Super Contributor
  • ***
  • Posts: 2730
  • Country: ca
Re: work around VHDL's lack of a preprocessor
« Reply #33 on: September 26, 2021, 11:29:49 am »
The problem the OP has is a code structuring one. First thing that needs to be done is for the command handling part to always support all commands (so the enumeration needs to be complete with all commands). Secondly a layer (translation table, function, whatever) needs to go between the input and command processing. That layer uses the variant type to check if a certain command is supported or not. This likely takes some restructuring of the code but that advantage is that determining which commands are supported by what type is in 1 location. This will help to keep code maintainable.
That's more useless talk. Show us the code already!
 
The following users thanked this post: Someone

Offline nctnico

  • Super Contributor
  • ***
  • Posts: 26892
  • Country: nl
    • NCT Developments
Re: work around VHDL's lack of a preprocessor
« Reply #34 on: September 26, 2021, 11:55:32 am »
The problem the OP has is a code structuring one. First thing that needs to be done is for the command handling part to always support all commands (so the enumeration needs to be complete with all commands). Secondly a layer (translation table, function, whatever) needs to go between the input and command processing. That layer uses the variant type to check if a certain command is supported or not. This likely takes some restructuring of the code but that advantage is that determining which commands are supported by what type is in 1 location. This will help to keep code maintainable.
That's more useless talk. Show us the code already!
Stop trolling and do your own homework. Maybe you can add something useful to this thread instead of trying to bait people into yet another VHDL versus systemVerilog thread. The OP uses VHDL and needs a solution that is written using VHDL.
« Last Edit: September 26, 2021, 11:58:36 am by nctnico »
There are small lies, big lies and then there is what is on the screen of your oscilloscope.
 

Offline asmi

  • Super Contributor
  • ***
  • Posts: 2730
  • Country: ca
Re: work around VHDL's lack of a preprocessor
« Reply #35 on: September 26, 2021, 12:23:00 pm »
Stop trolling and do your own homework. Maybe you can add something useful to this thread instead of trying to bait people into yet another VHDL versus systemVerilog thread. The OP uses VHDL and needs a solution that is written using VHDL.
There is no trolling. Show us the solution already. Or admit that there isn't one. Empty talk doesn't help anyone over here.
« Last Edit: September 26, 2021, 12:25:26 pm by asmi »
 

Offline Bassman59Topic starter

  • Super Contributor
  • ***
  • Posts: 2501
  • Country: us
  • Yes, I do this for a living
Re: work around VHDL's lack of a preprocessor
« Reply #36 on: September 26, 2021, 07:39:24 pm »
LOL you guys as always went deep into the woods in your attempts to defend that POS of a language :palm: As I understood, what OP wants is this (code in C so that even VHDLers would understand):
Code: [Select]
switch (op)
{
case OP_FOO:
//handing operation FOO
break;
case OP_BAR:
//handing operation BAR
break;
#ifdef OP_EXTENDED_1_SUPPORTED
case OP_EXTENDED_1:
//handing operation OP_EXTENDED_1
break;
#endif
#ifdef OP_EXTENDED_2_SUPPORTED
case OP_EXTENDED_2:
//handing operation OP_EXTENDED_2
break;
#endif
default:
//handing unknown operation
break;
}
Important point is that OP_EXTENDED_x opcodes are treated as unknown ones if such support is disabled. Now please show us how to implement this trivial code. And no, a bunch of generate's with copy-pasted switched for all possible permutations of supported opcodes is not acceptable.

So yes, "use SystemVerilog" is the only sureway solution to avoid having to deal with this garbage again.

Well, despite being a VHDL partisan with an allergy to all things Verilog, I will state that what asmi writes above is exactly what I want.

I will again note that VHDL-2019 actually supports this, but like I said, I expect tool support for VHDL-2019 to arrive sometime after the universe has gone cold and shrunk back into a pea-sized lump of coal.

And that still won't make me switch to SystemVeriilog. ;)
 

Offline Bassman59Topic starter

  • Super Contributor
  • ***
  • Posts: 2501
  • Country: us
  • Yes, I do this for a living
Re: work around VHDL's lack of a preprocessor
« Reply #37 on: September 26, 2021, 07:40:26 pm »
The 'generate' statement is the way to get this kind of things done.

Generate does not work within a process. Come on, this is freshman VHDL.
 

Offline Bassman59Topic starter

  • Super Contributor
  • ***
  • Posts: 2501
  • Country: us
  • Yes, I do this for a living
Re: work around VHDL's lack of a preprocessor
« Reply #38 on: September 26, 2021, 07:41:17 pm »
One way: make a component for the body of each case statement. That component's contents can have a generate statement that creates output based on what is being generated. There is zero code replication. In fact, closely related functions can be implemented using the same component.

You can't instantiate an entity within a process.

It's the same problem as trying to put a generate within a process.
 

Offline nctnico

  • Super Contributor
  • ***
  • Posts: 26892
  • Country: nl
    • NCT Developments
Re: work around VHDL's lack of a preprocessor
« Reply #39 on: September 26, 2021, 07:55:39 pm »
One way: make a component for the body of each case statement. That component's contents can have a generate statement that creates output based on what is being generated. There is zero code replication. In fact, closely related functions can be implemented using the same component.

You can't instantiate an entity within a process.

It's the same problem as trying to put a generate within a process.
Don't get too hung up on details; you can use a function or procedure as well. I'm just trying to help you while juggling a boat load of other projects in my mind (none of them dealing with VHDL so forgive me for not having that clear). However, looking at the big picture I see that the root of the problem is the overall structure of how you organised your code.

« Last Edit: September 26, 2021, 07:59:37 pm by nctnico »
There are small lies, big lies and then there is what is on the screen of your oscilloscope.
 

Offline Bassman59Topic starter

  • Super Contributor
  • ***
  • Posts: 2501
  • Country: us
  • Yes, I do this for a living
Re: work around VHDL's lack of a preprocessor
« Reply #40 on: September 27, 2021, 05:47:41 am »
Attached is an archive of a small test design I hacked up to test the two suggested methods of implementing a command parser that has a way of not firing the case selector for commands we'd like to disable. As a side effect of disabling a command, a signal assigned in that select should also get optimized away if it is not referenced in higher-up code.

For purposes of discussion, the design has three variants: DEFAULT, A and B. In the default, all commands are handled. In A, some commands are disabled. In B, the other commands are disabled. The variant is set with a generic at the top level.

A command sets or clears an output, depending on the bit in the argument. If the command is valid, the signal cmd_ok is strobed. If the command is invalid (because it is disabled) the signal cmd_nok is strobed.

The two methods of disabling commands are:
1. a function is used to "filter" out invalid commands, based on the variant chosen. Commands not handled are "invalid." In the parser case statement, all possible commands are listed as selectors, but the commands not handled in a given variant have been "remapped" by the parser to the invalid command, so their selectors are never invoked.
2. in each case selector, if the variant chosen allows the command, it is handled: the output bit is assigned and cmd_ok asserted, otherwise the output signal is ignored and cmd_nok is asserted.

The source code is three files.

cmd_pkg.vhdl defines a few useful types and two functions. One function handles that remapping and outputs an enumerated type. The other simply converts the std_logic_vector command to that same enumerated type.

parser.vhdl is the parser. It has two architectures: one, called "filter," uses the filter method described above to get the case expression. The other, "nofilter," does as #2 described above and tests each case selector to see whether it should be handled in the chosen variant.

top.vhdl holds six different top-level entities. Three are for the "filter" parser, with variants default, A and B, and three are for the "no-filter" parser. This could have been boiled down to just two entities, filter and no filter, but the synthesizer doesn't allow setting a generic with an enumerated type from the command line. Please note: the top-level entities do not have the signals assigned in "unused" command case selectors. My real design is like that -- those signals simply don't exist.

In the synthesis directory is a Synplify Pro project file. I used the version of Synplify that ships with Lattice Diamond 3.12, which is Q-2020.03L-SP1.

(Interestingly, this version of Synplify claims to support VHDL-2019's conditional analysis feature -- the preprocessor! But, I didn't test it, because the point was to test how a synthesizer would handle the test cases.)

The project includes the three source files and has two implementations: "top_A_nf" and "top_A_f," for variant A with no filter function and with the filter function. The target is a MachXO2-1200, chosen for no good reason. The correct top level entities are chosen for both.

And the results:

In the filter version, the only obvious synthesis warning is for some input bits not being used. These bits would be assigned to output bits if the command wasn't filtered out. In the non-filter version, the output bits that are not used because their commands don't exist are never assigned, so we're told that. (also the same input-not-used warning is here.)

Let's look at the synthesis outputs.

Here is the RTL schematic of the "filtered command" parser. (The top level schematic is nothing more than ports connected to the parser.) It's down to three flip-flops for the outputs that are enabled (E, F, G) and two more for the OK and NOK flags. The command was turned into a one-hot vector, so three valid commands mean three command bits which are ANDed and drive the flops' enables. Clearly the filter did its job, there is no logic at all for the disabled commands.


Here is the RTL schematic for the "no filter" parser. It's all just ... more complicated.


Now the fun ... the optimized schematics. The top level schematics are the same for both versions, so I'll post only one (the "filter" version):


The parser schematic is highly the same for both versions. Both have one LUT per output (five outputs: three E, F, G flag bits, and the two OK/NOK bits). How the LUTs are configured are slightly different, but they boil down to the same exact resource usage, and of course they are functionally identical. Here is the "filter" parser schematic:


CONCLUSION!
Both styles result in the same resource use for this example. The signals associated with disabled commands are optimized away, as are the decoders for those commands. This is ultimately what I wanted.

So the question is, which should I (we, you) use? Possibly a matter of preference.

I will give an edge to the "no filter" version, where the test for whether the command is enabled is in the decoder selector. Why? Because in my design, the number of commands that are common to all variants is much greater than the number of variant-specific commands. It's a lot more obvious to see what's going on if you put the "if VARIANT = THISONE" in the handful of case selectors that care, rather than to bury the command disable/enable in a function in a package in a different source file. We all like to write code that is very obvious to the reader, right? Of course we do!

I hope this was enlightening, and it shows that we don't need no stinkin' preprocessor! All we need to do is to just ignore a few synthesis warnings about signals not being used or being optimized.
 
The following users thanked this post: nctnico

Offline asmi

  • Super Contributor
  • ***
  • Posts: 2730
  • Country: ca
Re: work around VHDL's lack of a preprocessor
« Reply #41 on: September 27, 2021, 11:41:49 am »
Well, despite being a VHDL partisan with an allergy to all things Verilog, I will state that what asmi writes above is exactly what I want.

And that still won't make me switch to SystemVeriilog. ;)
In my experience people use VHDL because they are too old/too lazy/too stubborn to learn SystemVerilog. I'm yet to meet a person who learned both languages and voluntarily chose VHDL over SV.

So I'll hazard a guess that all these "allergies" are just a lousy coverup for good old laziness.

Offline Just_another_Dave

  • Regular Contributor
  • *
  • Posts: 192
  • Country: es
Re: work around VHDL's lack of a preprocessor
« Reply #42 on: September 27, 2021, 12:29:49 pm »
Well, despite being a VHDL partisan with an allergy to all things Verilog, I will state that what asmi writes above is exactly what I want.

And that still won't make me switch to SystemVeriilog. ;)
In my experience people use VHDL because they are too old/too lazy/too stubborn to learn SystemVerilog. I'm yet to meet a person who learned both languages and voluntarily chose VHDL over SV.

So I'll hazard a guess that all these "allergies" are just a lousy coverup for good old laziness.

Well, in Europe VHDL is used because it is the language that most companies ask for in their job offers. Therefore, it is the language that universities usually teach in their EE degrees. Consequently, it is better to focus your efforts on learning about dynamic reconfiguration of FPGAs, reliability, IC design, etc. than learning another language
 

Offline asmi

  • Super Contributor
  • ***
  • Posts: 2730
  • Country: ca
Re: work around VHDL's lack of a preprocessor
« Reply #43 on: September 27, 2021, 12:38:39 pm »
Well, in Europe VHDL is used because it is the language that most companies ask for in their job offers. Therefore, it is the language that universities usually teach in their EE degrees. Consequently, it is better to focus your efforts on learning about dynamic reconfiguration of FPGAs, reliability, IC design, etc. than learning another language
You still got to learn both at least to some degree because chances are you are going to have to work with third-party IPs written in another language. So you can only really ignore other languages if you are a hobbyist and can afford to roll your own, in professional setting you will have to deal with both.

But I was talking about personal choice given both options are on the table. I've never met a VDHL person who also knows SystemVerilog well, but I've met a plenty of SV people which also know VHDL.
« Last Edit: September 27, 2021, 12:41:19 pm by asmi »
 

Offline Just_another_Dave

  • Regular Contributor
  • *
  • Posts: 192
  • Country: es
Re: work around VHDL's lack of a preprocessor
« Reply #44 on: September 27, 2021, 01:07:31 pm »
Well, in Europe VHDL is used because it is the language that most companies ask for in their job offers. Therefore, it is the language that universities usually teach in their EE degrees. Consequently, it is better to focus your efforts on learning about dynamic reconfiguration of FPGAs, reliability, IC design, etc. than learning another language
You still got to learn both at least to some degree because chances are you are going to have to work with third-party IPs written in another language. So you can only really ignore other languages if you are a hobbyist and can afford to roll your own, in professional setting you will have to deal with both.

But I was talking about personal choice given both options are on the table. I've never met a VDHL person who also knows SystemVerilog well, but I've met a plenty of SV people which also know VHDL.

Maybe it is something related to the type of applications that they design, but the companies for which I have worked for didn’t allow us to use any IP programmed in a different language to VHDL
 

Offline asmi

  • Super Contributor
  • ***
  • Posts: 2730
  • Country: ca
Re: work around VHDL's lack of a preprocessor
« Reply #45 on: September 27, 2021, 02:31:23 pm »
Maybe it is something related to the type of applications that they design, but the companies for which I have worked for didn’t allow us to use any IP programmed in a different language to VHDL
I guess so, in my experience (admittedly not very long) I had to deal with third-party components written in all languages - regular Verilog, and VDHL. While I prefer SV, but I know enough of other languages to read and understand the code, and do some debugging if integration doesn't work like it should.

Offline Bassman59Topic starter

  • Super Contributor
  • ***
  • Posts: 2501
  • Country: us
  • Yes, I do this for a living
Re: work around VHDL's lack of a preprocessor
« Reply #46 on: September 27, 2021, 02:44:02 pm »
Well, despite being a VHDL partisan with an allergy to all things Verilog, I will state that what asmi writes above is exactly what I want.

And that still won't make me switch to SystemVeriilog. ;)
In my experience people use VHDL because they are too old/too lazy/too stubborn to learn SystemVerilog. I'm yet to meet a person who learned both languages and voluntarily chose VHDL over SV.

So I'll hazard a guess that all these "allergies" are just a lousy coverup for good old laziness.

Thank you for impugning our cocksmanship.
 

Offline SiliconWizard

  • Super Contributor
  • ***
  • Posts: 14445
  • Country: fr
Re: work around VHDL's lack of a preprocessor
« Reply #47 on: September 27, 2021, 11:17:22 pm »
LOL you guys as always went deep into the woods in your attempts to defend that POS of a language :palm: As I understood, what OP wants is this (code in C so that even VHDLers would understand):
Code: [Select]
switch (op)
{
case OP_FOO:
//handing operation FOO
break;
case OP_BAR:
//handing operation BAR
break;
#ifdef OP_EXTENDED_1_SUPPORTED
case OP_EXTENDED_1:
//handing operation OP_EXTENDED_1
break;
#endif
#ifdef OP_EXTENDED_2_SUPPORTED
case OP_EXTENDED_2:
//handing operation OP_EXTENDED_2
break;
#endif
default:
//handing unknown operation
break;
}
Important point is that OP_EXTENDED_x opcodes are treated as unknown ones if such support is disabled. Now please show us how to implement this trivial code. And no, a bunch of generate's with copy-pasted switched for all possible permutations of supported opcodes is not acceptable.

So yes, "use SystemVerilog" is the only sureway solution to avoid having to deal with this garbage again.

Well, despite being a VHDL partisan with an allergy to all things Verilog, I will state that what asmi writes above is exactly what I want.

As you saw later on, I would rather say: no, you *thought* that's what you wanted. But there are more elegant ways to do it in VHDL that get you the exact same thing. As I said, many VHDL features are equivalent to a fancy preprocessor. That's what you could see for yourself.

VHDL has strong similarities with ADA, which doesn't need a preprocessor either for generic programming. Thinking of using a preprocessor mostly comes from our habits with C. For lack of a better approach. So yeah, properly using VHDL for generic programming requires a slightly different mindset and knowing the language a bit better.

Now if warnings about removed logic and removed signals annoy you... well. In a moderately complex design, there will be tons of those warnings, even when there are no conditional exclusions. That's part of logic optimization. Many signals can get optimized out due to being logically equivalent to others in some way. So that doesn't make much difference...

Now you could also do this with 'if generate' statements, which would completely exclude some parts of code conditionally. In the case you showed, that would mean splitting your decoder into several processes/or even entities, which would be pretty cumbersome - and would need additional steps for combining the outputs of the various parts together. I wouldn't recommend it here. (That's what I think nctnico suggested at some point?) But that would be yet another approach.

VHDL-2019 additions look nice, but frankly we can do without them. And, I wouldn't hold my breath for tools support any time soon...
 

Offline nctnico

  • Super Contributor
  • ***
  • Posts: 26892
  • Country: nl
    • NCT Developments
Re: work around VHDL's lack of a preprocessor
« Reply #48 on: September 28, 2021, 12:35:06 am »
Yeah, bolting on C-isms to a language is never a good idea. Borland Delphi from the early 2000's comes to mind. What a steaming pile of rubbish!  :-BROKE

Just for clarity: I didn't suggest to break the logic that handles the commands into several pieces but to handle it before (the filtering). It is just that my brain isn't set to VHDL at this moment.
« Last Edit: September 28, 2021, 12:36:55 am by nctnico »
There are small lies, big lies and then there is what is on the screen of your oscilloscope.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf