Dave, As I can see there is an open discussion thread on 'Type parameters, typedefs, and general BNF semantics'. Hopefully this will address also issues of hierarchical references to the types rised here. But following your answer I want to provide some additional points of view that mayby were not expressed elsewhere. > The alternative for accessing types across the hierarchy is to put your types in packages. I understand what are the possibilities in language following current state of the LRM. But sometimes moving types definitions into a package or unit scope, although provide some technical solution, may not satisfy user's needs in making reusable code. Just consider following example of possible coding style: module ProtocolClientA; typedef byte[4] data_type; task send(data_type data); ... endtask function data_type receive; ... endfunction endmodule module ProtocolClientB; typedef int[8] data_type; task send(data_type data); ... endtask function data_type receive; ... endfunction endmodule if '::' was allowed for accessing a typedef from module, than a following code snippet could be used in a testbench part: <client_type> uut(); ... <client_type>::data_type a, b; ... uut.send(a); b = uut.receive(); in example: ProtocolClientA uut(); ... ProtocolClientA::data_type a, b; ... uut.send(a); b = uut.receive(); ProtocolClientB uut(); ... ProtocolClientB::data_type a, b; ... uut.send(a); b = uut.receive(); also this would allow to enclose the code snippet into parametrized unit: program #(type client_type) protocol_test; initial begin client_type uut(); ... client_type::data_type a, b; ... uut.send(a); b = uut.receive(); ... end endprogram and than use it in a fairly simple way: protocol_test#(ProtocolClientA) testA(); protocol_test#(ProtocolClientB) testB(); Now notice that: - currently such testbench code can be done only if a protocol client classes were implemented on a class basis, - it cannot be done if protocol client classes were implemented on a module basis, (for some reason user may prefer to define clients as part of the design hierarchy ...) Moving types definitions to the (common) package scope is not a solution here - it will not allow to keep same name ('data_type') for both type definitions - which is a foundation for this reusable testbench code construction. And notice that the in example above none of the problems you mentioned (hierarchical references to the parameters, forward references to the types) occur. So how to explain to the user: why he is forbidden to refer simple type definitions hierarchically ? Clearly, '::' usage limitation to the class and package scopes only is too strong penalty, just because of some complex corner cases. Of course a little more advanced example of hierarchical references to the parametrized module types will unlikely lead to hierarchical references to parameters. This is why the hierarchical references to parameters becomes much more important option in SV, than it is was in Verilog where it is locked by LRM . It is important for SystemVerilog to keep backward compatibility with Verilog. But to satisfy this requirement it is enough to keep Verilog rules for Verilog subset of constructs. New constructs of a SystemVerilog do not have to follow exactly same rules. Having this in mind, I believe that some of the problems you've point out , if considered separately, could have their solutions: >The problem here is compilation order dependencies. In general, Verilog does not allow you to refer to hierarchical references to parameters in declarations because it needs to >impose a strict ordering of parameter overrides during elaboration. This rule in Verilog was to protect user from making circular dependencies between parameters and to easy elaborator job. But notice that even with hierarchical references to parameters not every case must contain circular dependencies. Lot of cases will stand for useful coding styles. Just let's relax this Verilog rule in SV LRM and let the elaborator to find the proper order of the parameters initialization or to detect and report circular dependency ... >Interface types are a special case because the port connection imposes an ordering that the elaboration process can follow. I think that the language LRM better shall not attempt to control the way how the elaboration process is done. It is just out of LRM scope - how the compilation and elaboration processes are organized in each system. An attempt to impose order of the elaboration process results in unnatural syntax and semantic construct - as in case of interface types. The elaborator shall be able to find the right order of processing on its own ... >Another problem that is harder to explain is the fact that Verilog allows modules to be referenced before being compiled. >Even with that flexibility, Verilog still requires simple >identifiers to be declared before referenced. [...]. >There is even a stronger parsing restriction for types, [...], which requires a type identifier to be known to be a type before it can be referenced. Indeed Verilog allows modules to be referenced before (or even without - for compilation phase) their definitions. This is an important feature for effective compilation of large netlists, where actual modules definitions are irrelevant for the compilation task. But - as you mentioned: even in Verilog this rule do not apply to all definitions - Verilog still requires simple identifiers to be declared before referenced. The hierarchical reference to type, especially if made with '::' operator - as a SV construct - may require a type identifier to be known at least to be a type name, without breaking up backward compatibility with Verilog. This would also imply that the module definition must come first, before a typedef from within the module can be referenced externally. As a result, allowing hierarchical references to types do not have to imply allowing references to type names prior to the type definition or at least notice that the name is a type. Regards, Mirek -----Original Message----- From: Rich, Dave [mailto:Dave_Rich@mentor.com] Sent: 12 października 2007 18:54 To: Mirek Forczek; Vreugdenhil, Gordon; danielm Cc: sv-ec@server.eda.org Subject: RE: [sv-ec] reference to class definition nested in module/program /interface Mirek, You've should look back at the e-mail threads on the sv-bc for the last 3 months. The alternative for accessing types across the hierarchy is to put your types in packages. The key thing that Verilog has that none of the other OO languages you mention have is parameterized hierarchical elaboration. It is essentially a distinct form of object orientation that gives you the ability to do hierarchical references which the other languages don't have. The key thing that Verilog doesn't have that that SV adds is a type system similar to the other OO languages you mention. Problems come in is when you try to blend the two systems. The easiest to problem to explain is the parameterized elaboration. If you have: module mod #(parameter N=2)(); typedef int arr[N]; endmodule and then you try to module bod; mod::arr A; endmodule module top; mod #(3); m1() mod #(4); m2() bod bod(); endmodule Which instance of mod would you be referring to in bod? Then there's module bod; top.m1.arr A; endmodule The problem here is compilation order dependencies. In general, Verilog does not allow you to refer to hierarchical references to parameters in declarations because it needs to impose a strict ordering of parameter overrides during elaboration. Interface types are a special case because the port connection imposes an ordering that the elaboration process can follow. Another problem that is harder to explain is the fact that Verilog allows modules to be referenced before being compiled. Even with that flexibility, Verilog still requires simple identifiers to be declared before referenced. This is a parsing requirement that came from Pascal, one of Verilog's progenitors. There is even a stronger parsing restriction for types, which I am currently writing up a mantis issue on, which we agreed to in a recent face-to-face meeting on this subject, which requires a type identifier to be known to be a type before it can be referenced. There are two ways to accomplish this across the hierarchy: one is through packages, and the other is though hierarchical type parameterization. for example, through packages package pkg; typedef struct {int A;} s_t; endpackage module A(); pkg::s_t i; endmodule module B#(type T=int)(); pkg::s_t i; endmodule module top; A a(); B b(); initial a.i=b.i; // legal assignment endmodule Through hierarchical type parameterization. module A#(type T=int)(); T i; endmodule module B#(type T=int)(); T i; endmodule module top; typedef struct {int A;} s_t; A #(s_t) a(); B #(s_t) b(); initial a.i=b.i; // legal assignment endmodule -- This message has been scanned for viruses and dangerous content by MailScanner, and is believed to be clean.Received on Fri Oct 19 01:27:54 2007
This archive was generated by hypermail 2.1.8 : Fri Oct 19 2007 - 01:28:02 PDT