fabianschuiki / llhd

Low Level Hardware Description — A foundation for building hardware design tools.
http://www.llhd.io
Apache License 2.0
392 stars 30 forks source link

Minor typo? + suggestion about the "any type" #122

Closed gameboo closed 4 years ago

gameboo commented 4 years ago

Hi,

I am not certain about this one, but I assume it is not meaningful to create a var of a signal, or a sig of a signal or of a pointer?

If so, maybe it would make sense to split the table where the types are defined into the "basic type" or something like this which would exclude the T* and T$, and review all instances of the phrase

T may be any type

in the document to make sure the specific subset of allowed types is referred to?

If this makes sense, I am happy to push a couple more commits on the PR to address that.

fabianschuiki commented 4 years ago

Whether T*$ or T$* makes sense is a good question. From what I've seen until now, it is not really necessary. However I have the feeling that there may be cases where you would want T$* in order to keep signal pointers in a data structure in some test bench. Not sure about this yet, though. But there is a lot of weird stuff in SystemVerilog :smiley:.

In synthesizable code there is likely to be no use for these, and your changes apply. But I'm wondering if it makes sense to rule things out straight from the beginning. Maybe we could try to come up with examples of things you can write in an HDL that becomes hard to express in LLHD if T*$ or T$* is unavailable!

For example, how about:

Any thoughts?

gameboo commented 4 years ago

Any thoughts?

I rapidly get out of my depth here as my knowledge of fancy verilog features is fairly limited (and of VHDL basically only as a student 10 years ago or so...). So for what it's worth given my limited experience...

First, I would naively say that T$$ is meaningless, and T** is legitimate. Do you think this is true?

Then, regarding the other two fun ones, I don't think I was considering non synthesizable code properly (I probably was blinded by the "do everything as a native call with extern" from #121 ).

I think I can completely see that a T$* could make sense in a non synthesizable context, and it indeed makes no sense to artificially restrict the language on that one. I am going to read up a bit on access types and the likes to see if I can think of any nice use case.

I am having a much harder time convincing myself about the use of T*$. In my mind, the possibly erroneous shortcut I make is: a signal T$ must carry a values of type T that can exist on wires, and T* never exists on wires (this last part makes me re-read section 2.5.8 of the paper... I am not familiar with the algorithms used to lower stack and heap instructions to structural LLHD, but I was under the impression that the notion of T* disappeared after running them ?). Does this reasoning break?

So if I try to sum up my newest mental model of LLHD types after reading your answer, I guess it would go something like "if T is neither a signal nor a pointer nor an array or struct thereof then we can have types of the form T followed by zero or one $ followed by zero or more *".

I suppose iN, nN, lN and void are not so interesting, but for exhaustiveness's sake, I should probably also wonder about the meaning of time$ and time*... (well mostly time$ I guess...)

programmerjake commented 4 years ago

So if I try to sum up my newest mental model of LLHD types after reading your answer, I guess it would go something like "if T is neither a signal nor a pointer nor an array or struct thereof then we can have types of the form T followed by zero or one $ followed by zero or more *".

Don't forget about pointers to arrays or structs that contain pointers (or maybe even signals?), those should be valid

gameboo commented 4 years ago

So if I try to sum up my newest mental model of LLHD types after reading your answer, I guess it would go something like "if T is neither a signal nor a pointer nor an array or struct thereof then we can have types of the form T followed by zero or one $ followed by zero or more *".

Don't forget about pointers to arrays or structs that contain pointers (or maybe even signals?), those should be valid

Yes I agree.

The essence of what I was trying to emphasise was that there is at most a single level of $ and it has to be the nested-most level of indirection if present.

I was not trying to exclude pointers to arrays or structs of pointers / signals but ended up with some unfortunate convoluted wording. Apologies for that.

fabianschuiki commented 4 years ago

This is a very interesting discussion. I'm inclined to agree that multiple levels of $ might be rather pointless. But then, with SystemVerilog's test bench capabilities, you can probably have a variable (signal) with struct type, which contains a reference to another signal, which ends up being T$*$. Of course synthesizing this is highly unlikely to suceed :smiley: -- but that's not the only target for LLHD. As @gameboo points out, there are transformation passes that try to get rid of stack/heap memory (which is a necessity for synthesis), but they don't have to succeed in order for an LLHD input to be useful e.g. for testing/verification.

The same goes for time, btw. In SV you can do something like:

time t = 1ns;
bit x = 0;
initial begin
    t <= #10ns 2ns;
    repeat(20) #(t) x = ~x;
end

Which would essentially toggle x every 1ns for the first 10ns, then switch to 2ns toggles. Totally crazy, but it's there. And if we exclude this, you can be sure that someone will cook up some testing code that uses it :stuck_out_tongue:.

gameboo commented 4 years ago

Interesting yes. I agree that valid SystemVerilog allowing for these things certainly mandates that these be expressible in LLHD.

One more or less relevant note I have on that topic is that beyond what's allowed, I like that tools help me with what's sensible: I can picture myself writing SystemVerilog eventually intended for synthesis and which happens to use advanced features, simulate and debug it for a while only to discover some error when trying to synthesize much later and feel betrayed by the tools who let me hope for longer than they could have... Hopefully there are warnings there...

Of course synthesizing this is highly unlikely to suceed :smiley:

Out of curiosity, is there any scenario you can think of in which a $ nested under a $ synthesizes?

Regarding the PR itself, what do you think about having a few sentences under the Type System section of the document stating that all combinations of $ and * are allowed and expected to map to some defined behaviour in simulators, and only a subset of those are expected to yield meaningful circuits (or something along those lines)?

fabianschuiki commented 4 years ago

One more or less relevant note I have on that topic is that beyond what's allowed, I like that tools help me with what's sensible: I can picture myself writing SystemVerilog eventually intended for synthesis and which happens to use advanced features, simulate and debug it for a while only to discover some error when trying to synthesize much later and feel betrayed by the tools who let me hope for longer than they could have... Hopefully there are warnings there...

I can relate, happens to me all the time. Especially if you have to move between different tools from different vendors, you're stuck with a not-so-well-known subset of the language. As it becomes more evident which parts of LLHD are synthesizable, we can start to warn the user about non-synthesizable constructs early on in the language frontends.

Out of curiosity, is there any scenario you can think of in which a $ nested under a $ synthesizes?

Well technically I think you could describe a transmission gate/analog switch with it, but in a very awkward way. However I could see the use of some data structures, where $s are indirectly nested` being optimized away such that it becomes synthesizable. Pretty wild corner cases, though.

Regarding the PR itself, what do you think about having a few sentences under the Type System section of the document stating that all combinations of $ and * are allowed and expected to map to some defined behaviour in simulators, and only a subset of those are expected to yield meaningful circuits (or something along those lines)?

Yes I think this is an excellent proposition. The spec is completely lacking any description of synthesizability of constructs, so this is an excellent step!

fabianschuiki commented 4 years ago

LGTM! Ready for merging from your side?

gameboo commented 4 years ago

Sure thing :)

fabianschuiki commented 4 years ago

Perfect, thanks a lot! :smiley: Merging.