|
From: Wesley J. L. <wj...@ic...> - 2013-01-20 19:22:32
|
On Thursday, January 17, 2013 18:45:58 Joshua Mangelson wrote: > I just committed the final copy of our projected PHDL Language Spec. > If everyone has time to look it over and make comments or ideas for > changes. That would be great! I've got a few comments. Let me add them here in order as they follow the specification document. I'll quote Pete in related sections as well so we can keep comments together. We can split each part into a separate thread if necessary. = Packages and Imports = The way the spec reads, it's unclear how packages and imports interact. Let's discuss some specifics, assuming I have a device "device1" and "device2" in package "package1", and a "device1" in the current package (for some cases) and a device called "package1" (in the last examples). This is how I would assume -- and kind of hope -- things work. If it doesn't work like this, let's talk about how it does work. Example #1: import package1; device device1 ...; // WORKS: package1.device1 // WORKS: package1.device2 // WORKS: device1 (refers to my local device1) // FAILS: device2 Example #2: import package1.device1; or import package1.*; device device1 ...; // FAILS here because device1 has been imported Example #3: import package1.device2; device device1 ...; // FAILS: package1.device1 (because it was not imported) // FAILS: package1.device2 (because device2 was imported, not package1) // WORKS: device1 (refers to my local device1) // WORKS: device2 (refers package1.device2) Example #4: import package1.*; // FAILS: package1.device1 (because * was imported, not package1) // FAILS: package1.device2 (because * was imported, not package1) // WORKS: device1 (refers package1.device1) // WORKS: device2 (refers package1.device2) Example #5: import package1; device package1 ...; // FAILS here because package1 has been imported Example #6: import package1.* device package1 ...; // FAILS: package1.device1 (because * was imported, not package1) // FAILS: package1.device2 (because * was imported, not package1) // WORKS: device1 (refers package1.device2) // WORKS: device2 (refers package1.device2) // WORKS: package1 (refers to my local device) Basically, this means that we only import names that are specifically asked for. If importing those names causes ambiguity, that it causes an error. These are strongly desired properties to avoid errors. Now, I see verbage in the "Qualified Namespaces" section that says that packages can be used even if they aren't imported. I'd suggest that defeats the purpose of having import statements and hierarchy at all, as it gloms lots of unnecessary things (package names) into a global namespace, and makes working around name conflicts between unrelated nets/devices/packages almost impossible to resolve. = Packages and Imports -- Transitivity = What about when a package imports things, then is imported? Take the following example: // in package1 device device1 ...; device device2 ...; // in package2 import package1.*; // in top-level package import package2; // can I use device1 here? I would propose that trying to use device1 there does NOT work. The default behavior should be that packages do not export names that they have imported. Otherwise, this breaks encapsulation and any abstraction guarantees you might hope for with hierarchy. If we want to be able to do this kind of thing (e.g. having a meta-package that imports certain devices and then makes them available for use) I would suggest we add an "export" keyword so that package can explicitly state what things that they have imported that they wish to export. The other choice is to make the use of device1 above always work. That would mean that the default is that packages always export all names that they can see, and leave it up to the user to be explicit and not use ".*" poorly. I'd argue that in this case, we've made ".*" a land-mine feature and it should be removed. For reference, this *EXACT SAME PROBLEM* came up in Python, and they had to do massive hacks to the language to avoid ".*" causing bugs while trying to maintain backwards compatibility. I'd say lets just get this right in the first place. = Required Attributes = I'd suggest that making attributes required in the *language* (as opposed to being required by a particular back-end) may be too heavy handed. For example, REFPREFIX is all blank everywhere? Okay, then your parts all get named "1", "2", "3", etc. If you don't like it, add a REFPREFIX. If that doesn't work with some tool's backend, then it can add a default REFPREFIX (like forcing a "U" in front or whatever). Why should PHDL itself care? No FOOTPRINT attribute? Okay, then it's blank. Maybe the backend will complain, or maybe it won't. The PHDL language itself shouldn't tell you what to do. Same for LIBRARY. What if my backend doesn't even use libraries? Also, I really dislike the uppercase REFPREFIX, FOOTPRINT, and LIBRARY. Why all uppercase? Nothing else in PHDL (or modern computer languages) is all UPPERCASE. My belief is that the PHDL language (as opposed to backends) should treat all attributes as just pass-throughs. PHDL should not interpret them in any way. Specific back-ends (e.g. the PADS backend) may be written so as to expect or require certain attributes to be set. DRC tools could verify that certain attributes are set, or look for and warn about attributes set that aren't used by a certain system. Both of those might be built into the same compiler implementation. But the PHDL language itself has no business telling me what my attributes should be. Same thing goes with even the REFDES and PINCOUNT attributes. Its totally fine for these to be used by various backends, (netlisters, DRCs, BoM generators, etc) but the PHDL language itself should just treat them like any other attribute. This leaves the language much more flexible and extensible by users. I know in my own designs, I will use many, many more DRC-related attributes, because I'm a static-checking nut; but I don't want them cooked into the PHDL language. == Attributes on Everything == Attributes should be placeable on everything. Devices (check), Instances (check), Pins (not currently possible), and Nets (check). We really want to have a uniform syntax to apply attributes to all of these objects. == Pin Types == On Friday, January 18, 2013 07:17:47 Peter Dudley wrote: > PinType - Do we really want to have all those PinType reserved words, > "pin", "inpin", "outpin",. There are 11 of them. I remember that Wes > had some concern about this feature. I know having this was a > suggestion from me to allow error checking but let's do what really > makes sense. I love being able to statically check a design for correctness, but I'm strongly against the keyword-based pin type syntax. I think this kind of thing should be handled in a uniform way with pin attributes, which we can already support very easily and consistently. First, the names are confusing. Nobody knows what "oepin" is. Most engineers might guess something like "output enable?". What's a "passpin"? Something that just passes through a signal? Even though I've looked at this many times, when I went to comment on them this time, I could remember what those two were supposed to be until I read the description. Second, the categories that we have: in, out, inout, power, supply, open- collector, open-emitter, tri-state, passive, and no-connect are not exhaustive, are weirdly overlapping. What's the difference between a power pin and a supply pin? I can imagine, but to most engineers those are synonyms. What about pins like a Xilinx FPGA's DONE? You tell me what pin type it is from the list above, and I'll tell you why you are wrong. Next, its unclear how this would even work in practice. A regulator's output is a suppin (I'd suppose). It goes directly to an inductor's passpin. Everything else using that power supply is just hooked up to the inductor's passpin. The supply pin never touches anyone's pwrpin. No DRC can do anything about this unless it can model the parts themselves (e.g. it knows what an inductor is). Even, matching inputs, outputs and bidirectional signals is a start (and is what most graphical schematic tools support -- mostly just for looks, not DRC), but falls apart quickly. I have an oscillator output that's an outpin, and it goes to my processor's clock input which is an inpin. Except, it doesn't really, because it hits a series source termination resistor with passpins on both sides first. Now, when I hook it up wrong (to a processor output) all is well in the DRC, because outpin -- passpin and passpin -- output. These kind of issues prevent our current ugly, hard-coded, non-extensible, keyword-based pin types into an failed, overreaching system right from the start. To make matters worse, they don't even help check the most common errors like, "did I hook up a 1.8 V line to the FPGA's 3.3 V bank on accident?". That kind of question -- and *all* others -- could be answered fairly simply by just allowing the user to annotate pin attributes however they wish and process the reports in whatever way makes sense (manually checking, a custom DRC tool, etc). If we want to later canonize a DRC tool or cook it into the language in a good way, I'd suggest we do that as its own separate effort once the language is robust, because its more complex that it sounds and has to be done in a user-controlled-and-user-extensible-per-design way to have any real-world value. == Info Statement == > InfoStatement - Is this much better than regular comments? I think it > could be and probably does no harm. My guess is we would want the > InfoStatement information to go into a report of some kind. The "Layout > Guy" would be able to read that report for guidance. On the other hand, > I would probably not use that feature. I always write up a separate > document to explain special layout requirements and send it to the > Layout Guy along with the netlist data. The idea was supposed to be to make generating special layout requirements documents automatically. I think this was a fun idea, but really won't work in practice -- several (now obsolete) computer languages have tried this kind of thing in the past. I'd say to ditch the info statement syntax and, if desired, do automatic comment extraction via tools like doxygen if so desired. == Reference Designator Prefix Combining == > REFPREFIX - Here you say, " In either case the "/" character will be used > as a delimiter between the REFPREFIX and the original reference > designator." I don't think we want to include any kind of delimiter in > the RefDes string. It is desireable to be able to print the RefDes onto > the printed circuit board so characters are precious. I think "XYR17" > might be acceptable as a refDes but "X/Y/R17" is probably not acceptable > to most designers. Also, I suspect that many layout tools would not > accept the "/" character in the refDes string. I agree. Back-ends that use the REFPREFIX attribute should not tack anything in the REFDES that isn't requested by the user. If I want "XYR17", I'll give REFPREFIX attributes of "X", "Y", and "R". If I want "X/Y/R17", I'll give REFPREFIX attributes of "X/", "Y/" and "R". == Looping / Instance Array Simplication == > Inst array simplification - I did not get much comment back on my > suggestions about simplifying the inst array syntax that we have > presently. You can find my document on that subject in the git > repository under doc/inst_array_proposal.pdf. I think the changes I > suggest in there would make instance arrays work much more like the rest > of the PHDL language. Assigning REFDES to an inst array would be just > like assigning pin numbers to an array of pins on a device. It would > also eliminate the need for the combine() and this() operators. In > effect, pins would always combine(). I'm convinced that we absolutely must ditch the this() and combine() syntax. Sadly, I'm probably the one who originally pushed for such flexable instatiation syntax in the first place. It gives us a lot of power in a monadic functional style. But I think it takes too much in-head-processing (a lot like reading Haskell code) and is kind of a write-only feature that is hard to review and unfortunately I think inappropriate for our goals. Basically, its the part of PHDL that doesn't look like PHDL. That said, we *CAN'T* get rid of inst arrays. They are way too useful. Looping/arrays is fundamental But we *can* simplify them. > In discussions with other folk, I often find that combine() and this() > interfere with communicating the purpose and goals of the language. > Typically a conversations starts like this, "Hey, did you get an > opportunity to look at the PHDL stuff?". The response is something like > this "Yeah, I've never seen anything like that combine() operator" 45 > minutes later it is "Hey, maybe you could do this or that instead of the > combine() thing.." I think Pete's proposal has a lot of merit, although I'd change a few things about the syntax. I don't have time now to go into it, but I'm confident it has to be done. So let's continue this discussion, and I'll throw in my opinion next time around. =) == inst vs subinst == I think having design and subdesign makes sense, because subdesigns have to contain ports to be useful, and designs should NEVER contain ports. Having multiple subdesigns makes sense, but multiple designs probably means you pointed the compiler to the wrong files. So there is a real reason to have those be different. But, why do we need inst for regular devices and subinst for subdesigns? They share the same namespace, and subdesigns look like devices from the users perspective, even if the language secretly knows they are different. Let's just use "inst" for both, and get rid of the special magic non- attribute REFPREFIX that subinst uses. It can be put in an attribute just like any other if desired. == End == That's all I have time to write about for now. It's great to see we've got so much written up here. I think we'll be really happy once we get the spec really solid. Better to spend time now getting it right. =) |