Thanks, John, for the patience and clarity that it took to explain this (again). I accept the requirement that you should not be able to circumvent strong typing by going outside of a language. I also accept the observation that doing automated conversions is a bad idea, except under a finite number of specified circumstances. If I'm reading your message correctly, it seems that an oversimplified way to illustrate the main point is that this Verilog should be outlawed: typedef enum { red, green, blue, yellow, white, black } Colors; Colors c; c = <reference_to_some_VHDL_or_SC_thing_of_a_temptingly_similar_looking_enum >; I agree. There's still the question of what to tell the user to do instead. This is where my comments about needing a way to supply conversion functions comes in. It is possible to write a Verilog function to make this work: typedef enum { red, green, blue, yellow, white, black } Colors; Colors c; typedef enum { green, yellow, red, blue, white, black } ReorderedColors; ReorderedColors r; ... c = convert_colors(r); The function would look something like: function Colors convert_colors(input ReorderedColors r) ... It would be nice if something similar were possible for converting between SC/VHDL/Verilog types. I don't have a good answer for what it looks like, though. There's no way to write such a conversion function in any one language. I suspect the conversion would end up being in C/C++ with each language having ways to pass things to/from C/C++. I think that the kind of mixed designs you focus on determines whether the conversion functions are regarded as a nice thing to consider someday or an urgent capability. If you're mostly worried about passing class objects around, then life will be hard without conversions. If and when we figure out how to write the conversion functions, then it might be reasonable to say that you can connect a Verilog reg of type Colors to a VHDL port of type SimilarColors, provided that you have written the appropriate conversion functions. Just to clarify, I still agree with your requirements. Conversion functions, if they exist, should only be able to do the same kinds of things that could be done anyway within the language. ________________________________ From: owner-sv-xc@eda.org [mailto:owner-sv-xc@eda.org] On Behalf Of John Shields Sent: Tuesday, June 26, 2007 5:51 PM To: Bob Shur Cc: sv-xc@eda.org Subject: Re: further discussion on implications of typing rules Hi Bob, Thanks for taking the time to do this. Because there is no proposal and only arguments presented for a requirement,it is understandable that one might have questions. I don't want you to agree to something out of a misunderstanding. Wanting some examples to illustrate the requirement makes sense. As long as we don't go down a rathole of needing to see the answer for every type or related use case in order to accept the requirement, we are being smart. After all, requirements serve to guide the formation of the spec, to analyze all the details, and evaluate afterwards whether we achieved what we wanted. I'll try to get at your questions from the simplest of the strong types and perhaps the one that defies the desires of users who want the languages to do what they mean. I apologize for the length of this email as it is partly a style problem of mine. I hope it sharpens the argument. I also hope it addresses the comments that Michael Rohleder made in reply to your email. It is typical that well-known built-in types can be weakly typed and support automatic conversions between them that make sense. It is also typical that user defined types like enumerations, structures, and classes are strongly typed and there are no automatic conversions between them, except for conversions written by the creator/user of the types. For some types, the discerning author may say there is a possible analysis that would allow an automatic conversion and a check(possibly runtime) to validate whether the result is legal. For other types like unrelated class types, it is mostly obvious that it is not possible to infer any reasonable automatic conversion. No matter. The languages deny automatic conversion. Period. In SV, enumerations, structures and classes are strong types. It is generally easy to make the argument for classes that they are distinct types and, if they are not related by inheritance, that it makes no sense to allow assignments of one class type to an object of another class type. Let's look at enums and see how SV makes its argument. We can then easily see the same argument for structs and classes. An enumeration type is an integral type that has a user-defined set of named constants. An integral type is one of SV's basic integer data types or packed data types that can be treated as an integer. SV provides rules for automatically defining the encoding of enumeration constants and also allows user-defined encoding. The values may be disjoint. A couple of examples are: enum {red, yellow, green} light1, light2; // anonymous int type // c is automatically assigned the increment-value of 8 enum {a=3, b=7, c} alphabet; There are richer examples of the flexibility of SV enumerations. What does SV say about strong typing and enumerations? 6.17.3 Type checking Enumerated types are strongly typed; thus, a variable of type enum cannot be directly assigned a value that lies outside the enumeration set unless an explicit cast is used or unless the enum variable is a member of a union. This is a powerful type-checking aid that prevents users from accidentally assigning nonexistent values to variables of an enumerated type. The enumeration values can still be used as constants in expressions, and the results can be assigned to any variable of a compatible integral type. ... Enumerated variables are type-checked in assignments, arguments, and relational operators. Enumerated variables are auto-cast into integral values, but assignment of arbitrary expressions to an enumerated variable requires an explicit cast. Despite the fact that one can view an enumeration's value as an integer, one cannot make an assignment to an object of enum data using an integer value. It doesn't matter that it is in range or corresponds to one of the enumeration constant's value. So, typedef enum { red, green, blue, yellow, white, black } Colors; Colors c; c = green; c = 1; // Invalid assignment It doesn't matter that green and 1 have the same value. If I declare a different enumeration that is similar to colors in form and meaning(at least to me the author), I run into the same restriction, right? typedef enum { m_red, m_green, m_blue, m_yellow, m_white, m_black } MyColors; MyColors mc; mc = m_green; c = mc; The point is that, while SV allows objects of an enum type to participate in numeric expressions, it does not allow direct assignment of an numeric value to an object of an enum type. Strong typing enforces this kind of type checking to eliminate the possibility of illegal values being assigned to the object. What about if I place the same declaration of an enumeration in 2 different packages? They are distinct types. package p1; typedef enum { red, green, blue, yellow, white, black } Colors; endpackage package p2; typedef enum { red, green, blue, yellow, white, black } Colors; endpackage ... p1::Colors foo; p2::Colors bar; foo = red; bar = foo; //Illegal What I can do in SV, because the enumeration is an integral type and cast compatible with other integral types, is explicitly cast an integral expression to be of a specific enumeration type. As the author, I must write the cast expression;there is no automatic casting inferred. SV does understand how to do such a cast. So: typedef enum { red, green, blue, yellow, white, black } Colors; Colors c; c = green; c = Colors'(1); // valid explicit cast I used assignment statements and a very simple strong type to illustrate SV strong typing rules. It applies to arguments and actual connections to ports and parameters in SV as well. If the types are not assignment compatible, you cannot make the connection. What I illustrated with the enumeration data type examples where assignments were illegal are types that are not assignment compatible, though cast compatible. A key point in the discussion of the requirements for strong typing is that you should not be allowed to break this kind of strong typing in SV because you are using mixed language and making connection to VHDL strongly typed objects. I need to frame the rules for VHDL enumerated types next to complete the argument. VHDL enumerated types are strong types(as are all its types). An enumeration type, like an integer type, is a scalar discrete type which implies that each value of such a type has a position number that is an integer value. It is defined by a set of identifiers or character literals, each of which must be distinct. The position number of the first identifier is 0 and each subsequent one has the value 1 more that its predecessor. So, in contrast to SV, the encoding of enumeration can only be a fixed, 0 based encoding, the same as the default encoding in SV. Some examples are: type BIT is ('0','1'); variable foo : BIT; type Colors is (red, green, blue, yellow, white, black); variable shade : Colors; VHDL does not allow type casting, but does support type conversions between closely related types, but an enumeration type is not closely related to any other type. It is possible to take an integer value and, using an attribute of the type ( which you may consider a pre-defined function ) convert the integer to a value of the enumeration type. Using the variable shade from above: shade := green; shade := Colors'VAL(1); I may also write a similar example as I did with SV using the same type declaration in two different VHDL packages. The result is the same. They are 2 distinct and unrelated types. I'll note a couple of differences between SV and VHDL enums. First, there are enumerations in SV for which no equivalent VHDL enumerations can be constructed, namely those enumerations with non-default encoding. Secondly, VHDL supports a stricter model of strong typing for enumerations. Type casting in SV will allow you to assign a value to an enumeration type that is illegal for the type. It is not possible in VHDL to make that mistake. The VAL attribute will perform a range check and report an error for a value that does not correspond to a legal position number for the enumeration. Strong Typing for Mixed Language Now we can get back to the questions, using the enumerated type as example. Both SV and VHDL expect you to declare objects of the same enumerated type to be free to connect them across hierarchy. If I have an SV type declared like this: typedef enum { red, green, blue, yellow, white, black } Colors; It is clear to me that this is equivalent to a VHDL type declared like this: type Colors is (red, green, blue, yellow, white, black); But, if these are separate declarations, made in each language in some declarative region, they are also distinct, separate types. If I am cavalier about language rules and simply say that the shape of the types is enough to call them compatible across languages, then mixed language allows you to violate either languages rules. I can connect an object of one type in SV to an object of any of an arbitrary number of distinct types in VHDL that have the same shape. I can then connect such a VHDL object to another SV object of any of an arbitrary number of distinct types in SV. I have used hierarchy to break SV strong typing rules. The argument cuts both ways and I can break VHDL rules as well. This is just wrong and there is no justification for it. Not to belabor the point, but I don't need to pass objects through ports across a language boundary if I have hierarchical references that cross such a boundary. It is reasonable to state that we wish to use a single type, the "same" type in both languages. This is a type that can be shared across SV and VHDL. How could that be described? Well, we could define some new canonical form for the shared type that both language would parse and whose semantic meaning would be equivalent to the native enumerated type, but that is a poor solution. We can say that we may write the enumeration in either language and define the semantic rules such that there is a clear and unambiguous equivalent type in the other language. That is, there is a conformal map, 1 to 1, between the types. Now, there remain issues of where is the type declared and how does one reference the type across the languages. Important issues, but they are orthogonal to the discussion of this requirement. In the writeup of the requirement, I mentioned shared packages as a way to support shared types. Packages are a design units that will be reference-able across languages, as a consequence of the same naming and referencing rules we want to have for instantiations. Packages also are designed as mechanisms to organize and share declarations. That is the purpose they have in both languages, right? A shared package is a very transparent, user friendly way to have shared types and preserve strong typing. We also don't have to change either language to define such semantics. There are other ways. Here is one I don't like: hierarchical references to a type across languages. This is severely restricted in SV (for good reason) as it is and there is no mechanism in VHDL to do this, so we would have to change VHDL. What a high bar and long lead time. If you think about the fundamental language design issues...this would be a disaster. Here's another thought. I am not fundamentally opposed to also having some other way outside of the language for tools to create a mapping between type definitions in SV and VHDL that says "these types are 'the same'". I do believe it requires a lot more consideration of what can go wrong with the declarative approach, what kind of checking one might require to be enforced, and what declarations will be considered erroneous. "Erroneous" here is the precise term that means "in error, but not required to be detectable and may lead to unpredictable or disastrous results". I also think that any approach still has to conform to the strong typing requirement and can't be used to circumvent it. Applying the Argument to Other Types It's not difficult to look at the SV struct and the VHDL record and see how some structs and records are semantically equivalent. They must have the same ordered set of members, each of which must be of a type that is defined to be equivalent across the languages. The generality we desire starts first with a definition of what built-in and user-defined scalar types have a semantically equivalent type in the other language. For composite user-defined types, which of those are structurally equivalent mechanisms and what the requirements on its members must be to arrive at a semantically equivalent type to one defined in the other language. Where we do this, strong typing rules can easily be preserved. There will be types in one language which have no semantically equivalent type in the other language. If there are compelling use cases in which we feel we must deal with being able to connect objects of such a type to an object in another language with some "similar" type, let's see what they are. My belief is that most of those kind of cases will be connections that cannot be transparently made. There will be information loss, there will operational inconsistency, and the ability to ruin the conceptual integrity of those objects. That should not be standardized and does not need to be. In my view, it is the user who must write the conversion to define how the loss of information or synthesis/initialization of information will be done in user-defined conversion functions. What about user-defined classes and mixed language interoperability? SV and SC have classes, but VHDL does not. It is conceivable that semantic rules can be defined for some user-defined classes such that an equivalent class in the other language may be derived, but that may prove to be a difficult problem. If one cannot do that, the only other possibility is for the user to write conversions or the equivalent type themselves. The principal of protecting the semantics of strong typing are not in conflict with this. To be complete, there are 2 other aspects. First, let's consider the fact that there are a number of cases of weak types that we must deal with. These are well-known built-in or standard types that all tools support. We must define equivalence between these types that can be supported automatically. A vector of wires and a std_logic vector type both represent the same set of bits in hardware and RTL connections between them are required. Defining how well known types across languages relate to each other is an essential part of our specification. Lastly, there is the idea of an opaque or abstract type that represents the type of object from another language that is not representable. It can allow an object of that type to passed through design hierarchy from language A through language B and back to language A transparently. It requires changing language B, i.e., SV, VHDL, and (possibly) SC to allow this. It is high bar, longer lead time item and ...so far...the only one we are entertaining. Summary I think what Michael acknowledged and emphasized about Bob's concerns is the need for conversion functions in the difficult cases. If we do a solid job of defining where semantic equivalence exists betweens scalar types and composite types and where it does not, we will be able to address all the type connections that can be correctly and automatically connected. In both languages, one can always write user-defined functions that take an object of one type and convert to a value of another type. That takes us another solid step. What cannot be done is to write a function in language A that can return an object of a type that is not representable in language A. I can't take a record in VHDL and write a VHDL function to return a class in SV, can I? Anyone expect that we have to solve such a problem? Note, I can do the reverse, namely take a class in SV and write an SV function to return a struct. If that struct is a shared type then I can connect to an object of a record type in VHDL where the struct and record type are...the same type! Here what I have done is kept the loss of information in the domain of the owner of the class, SV. I can also pass a record back and within SV, use it to initialize an object of a class type. I hope you can see that many of the hard problems have to be owned by the user and can be designed using the features of the existing languages. I trust that we will come to wish for some features to be added to other languages to make better interoperability possible and we can advocate for them. I, for one, would like to see us get a solid initial foundation for interoperability. We certainly don't have to solve all the hard use cases in the first revision of the spec. Regards, John ----------- Bob Shur wrote: At last Wednesday's meeting I expressed confusion about the strong/weak typing proposal. I think most of my unease comes from not understanding the context of the discussion. Possibly the rest of this message is based on a misunderstanding of what was being suggested. If so, I apologize. If there was a proposal on the table, I wasn't clear on what it was. If the idea was to define strong/weak typing, I have no objection. I heard the idea that we should be careful to define things such that a if a language enforces strong typing then it should not be possible to circumvent that by mixing languages. This seems reasonable. I don't know when it applies, though. Some examples of where we're in danger of having this problem would help me. I'm also not clear on the definition of strong typing. For example, when you call a C++ function, you have to pass actual arguments that are convertible to the formal arguments. You can pass an A to a function(B) as long there's there an A::operator B or B(A) constructor. I'm not sure whether you're calling that strong typing or not. The example of an SC interface was given in John Shields' message of April 26, in which he said: For example, SC certainly has strong requirements for matching class types at its interface. Defining, generating, and using equivalent derived declarations to do type checking between SV or VHDL and SC should be part of the specification and implementation. I'm not sure what was meant by "equivalent derived declarations" here. My view is that where SC needs an object that implements some interface, the object has to be, in fact, a C++ object that implements the interface. There's not much choice, since the C++ code that makes calls to that interface is compiled by an off-the-shelf C++ compiler and assumes that the object it's calling is a C++ object that implements the interface. This object may not be the same one that user mentions-for example, if the user tries to bind a verilog class instance to a SystemC port we might create a behind-the-scenes C++ object that we bind to the SystemC port, with the behind-the-scenes object somehow linked to the Verilog class instance. I see no apriori reason why the Verilog object and the behind-the-scenes C++ object have to be the "same" type-only that operations on one can be translated to operations on the other. I'm happy with the idea of coming up with a way to enforce, or create by construction, "same" types in multiple languages. But I expect we will also need to come up with a way to populate a library with converters between types in different languages. In that case, the "same" types would become a special case in which the converters were automatable so the user would not have to think about them. If what I've attempted to express here does not conflict with what I was asked to vote on last Wednesday, then I'm happy to change my vote from "need more time" to "yes". -- This message has been scanned for viruses and dangerous content by MailScanner <http://www.mailscanner.info/> , and is believed to be clean. -- This message has been scanned for viruses and dangerous content by MailScanner <http://www.mailscanner.info/> , and is believed to be clean. -- This message has been scanned for viruses and dangerous content by MailScanner, and is believed to be clean.Received on Tue Jun 26 19:09:44 2007
This archive was generated by hypermail 2.1.8 : Tue Jun 26 2007 - 19:09:46 PDT