TWiki
>
P1076 Web
>
Vhdl2019CollectedRequirements
>
InterfaceAndBundleEnhancements
>
BundlesProposal
(2016-04-28,
RobGaddi
)
(raw view)
E
dit
A
ttach
---+ Bundles <br /><span data-mce-mark="1">%TOC%</span> ---++ Proposal Details * Who Updates: Main.LievenLemiengre * Date Proposed: 2016-04-12 * Date Last Updated: 2016-04-12 * Priority: high * Complexity: high * Focus: rtl, testbench ---++ Motivation This proposal explores a method to abstract over port lists in VHDL. ---+++ Current Situation Large parts of port lists are often duplicated multiple times across a design. The repetition occurs in port list definitions (in entities and components) and in port maps (in instantiations and configurations). This code duplication is a code smell, changing the name, type or position of a port may require changes to port definitions and port maps across the entire design. The repetition also causes excessively long instantiations that make the code harder to maintain. ---+++ Workarounds ---++++ Records There are two options * Split the record based on port mode * Many designs use this approach * This approach doesn't scale when you nest records * Make the record *inout* * Lose mode enforcement ---++++ Packages A package with signals can be passed as a generic to an entity. * No port modes * An unnatural code style because the package is passed as a generic ---+++ Goals * Maintainability * Manage port names & types in one place * Reuse parts of a port list to build bigger port lists * Readability * Reduce the verbosity of VHDL * Testability * A bundle can make it easier to write reusable tests. * New abstractions * Reusable operations that operate on bundles (use bundles in procedures & functions) * Reusable mapping operations (map functions) ---+++ Non-Goals This feature shouldn't change the way the simulator works. After elaboration, bundles should be expanded into ports and signals. ---+++ Success factors and risks Port lists are used very frequently in VHDL. The payoff of this function could be very big. The impact on the language will be big at the same time there should be no friction with existing features. The benefits should outweigh the added complexity and increased learning curve of vhdl. ---++ Requirements A general exploration of the requirements can be found [[InterfaceAndBundleEnhancements][here]]. TODO: list a reduced set of requirements specific for bundles, other requirements must be moved to separate enhancement requiests. ---++ Design exploration This is my interpretation of the requirements and how they lead to the design. These questions are more or less in-order, one question leads to the next. ---+++ What is the contents of a bundle? A bundle can contain the same things as a port_list. A port list element has a _kind_, a _mode_ and a _type_. Because a bundle has multiple kinds of information we call it heterogeneous. Kinds: * ports: references to signals * signals * _other_ bundles (but it can't contain itself) * shared variables: future work, not part of this proposal * vhdl-ams objects Modes: (only relevant for ports?) * for ports: in, out, inout, buffer * for bundles: modport * for shared variables: ??? * for vhdl-ams objects: ??? Type: see port_list rules ---+++ Can we build this feature on top of records? I suspect that there is a vastly simpler proposal using records *if* we drop the requirement that bundles contain *heterogeneous* data. TODO: explore this design (basically records + modports), other object can be passed via a generic package? Differences between bundles and records: * Records can have resolution functions, bundles can't * Bundles are a pure elaboration-time construct * You can have signals with a record-type and variables with a record type, bundles can contain both & thus they are neither variables nor signals. ---+++ What is the impact on signal resolution and the event model? * No resolution functions for bundles, the elements may or may not be resolved * No additional delta cycles when bundles are connected, this should work like ports * To get this behavior, all bundle connections need to be resolved at elaboration time ---+++ Should bundles have a type? * Subtypes of bundles: you can constrain the elements of a bundle like you can constrain the elements of a record * Arrays of bundles: the array element has a type * Subprograms with bundle parameters: a type for overloading ---+++ What variants/subtypes are there of a bundles? * Subtyping: constraining element types * modport * determine port modes * export a subset of bundle elements ---+++ What attributes should bundles have? * The same attributes as records? * new attributes?: * 'kind: is_signal, is_bundle, is_variable * 'mode: is_in, is_out, is_inout, … * I don't have practical use cases for these ---+++ Why 'bundle' and not 'interface' or something else? I suspect 'interface' is a often used as an identifier, so for backwards compatibility 'bundle' may be a better choice. ---++ Proposal ---+++ Bundle declaration ---++++ Declaration A simple bundle declaration: <verbatim>type bundle_t is bundle signal sig1 : std_logic; sig2 : std_logic; -- the default kind is signal signal sig3 : std_logic_vector; signal sig4 : std_logic_vector(7 downto 0); variable var : shared_integer; -- a shared variable (future: not part of this proposal) end bundle bundle_t;</verbatim> * In a bundle declaration we declare the element kind and type * Bundle elements initially don't need a mode, nor do they need to be constrained * The only useful place to declare bundles is in a package but I see no reason to restrict the use. A nested bundle declaration: <verbatim>type nested_t is bundle signal sig1 : std_logic; signal sig2 : std_logic_vector(7 downto 0); signal sig3 : std_logic_vector; bundle nested : bundle_t; -- a nested bundle end bundle nested_t;</verbatim> * Bundles can be nested * Nested bundles don't have a modport! Grammar: <verbatim>[§ 6.5.2] interface_object_declaration ::= interface_constant_declaration | interface_signal_declaration | interface_variable_declaration | interface_file_declaration | interface_bundle_declaration [§ ?.?.?] interface_bundle_declaration ::= bundle identifier_list : subtype_indication [§ 5.3.1] composite_type_definition ::= array_type_definition | record_type_definition | bundle_type_definition [§ ?.?.?] bundle_type_definition ::= bundle ?? generic_list and/or discriminant_list ?? port_list end [bundle] [bundle_type_simple_name]</verbatim> ---++++ Bundle subtype declaration <verbatim>subtype nested_subtype_t is nested_t(sig2(7 downto 0));</verbatim> We reuse the syntax used for record subtyping. ---++++ Modport declaration A modport is applied to a bundle * It sets the mode of individual elements * It doesn't have to include all elements How should modports work though? * A modport is bound to a specific bundle! * Where should it be defined? * Outside of the bundle * My choice * Alows to create other modports separate of the bundle definition, for example in another package * Inside of the bundle * The alternative * The person who defines de bundle defines all possible modports <verbatim>modport master_of_bundle of bundle_t is sig : out; end modport master_bundle_t; modport master_nested of nested_t is sig1, sig2 : out; nested : master_of_bundle; end modport master_nested; modport master_slave of nested_t is sig1, sig2 : in; -- not all elements are exported end modport master_nested;</verbatim> grammar: <verbatim>TODO</verbatim> ---++++ Bundle instantiation Bundles are neither signals, variable or files so we need a new kind of declaration During instantiation we can choose to map objects into the bundle or create new objects Raw bundle instantiation: <verbatim>signal clk, rst : std_logic; bundle b : bundle_t := (clk => clk, rst => rst, others => new);</verbatim> You can't connect ports into a raw bundle instantiation <verbatim>bundle invalid : nested_t := ( sig1 => input_port, -- not valid: ports have a mode, you can't turn ports into signals others => new -- create the other elements )</verbatim> Bundle with modport instantiation can connect ports: <verbatim>bundle valid : master_nested(nested_t) := ( sig1 => input_port, -- valid if the modport is respected in -> in others => new -- create the other elements )</verbatim> ---++++ Array of bundles declaration We use the normal array type declaration to create an array of bundles. <verbatim>type bundle_array is array(0 to 10) of bundle_t;</verbatim> Note: no modport ---+++ Usage in a port list ---++++ In a port_interface_list Bundle usage in port lists (found in entity declarations, component declarations & block statements) A modport is required now! You can apply the modport to an array! <verbatim>entity e is | component c is | blk : block is port ( signal clk : in std_logic; -- already legal rst : in std_logic; -- short form bundle bnd : master(bundle_t); -- bundle in port-list bundle bnd_array : master(bundle_array) ); end entity e; | end component c; | begin end block blk;</verbatim> ---++++ In a parameter_interface_list Bundle usage in subprograms (functions and procedures) A modport is required now! <verbatim>procedure p ( signal sig : in std_logic; bundle bnd : master_nested(nested_t) ); function f ( signal sig : in std_logic; bundle bnd : master_nested(nested_t) ) return boolean;</verbatim> ---+++ Instantiation Bundle usage with a port map -- To avoid nested mapping so I added a map function <verbatim>architecture top of e is component c is port( clk : in std_logic; rst : in std_logic; bundle bundle_v1 : master(bundle_t); bundle bundle_v2 : master(bundle_t); bundle bundle_v3 : master(bundle_t); bundle bundle_ar : master(bundle_array_t) ); end component c; -- note: don?t have a modport! bundle bundle_v : bundle_t := (clk => clk, rst => rst, others => new); bundle bundle_ar : bundle_array_t; -- incomplete initialisation is an elaboration issue? bundle bundle_slv : slave(bundle_t) := ( /*only bind slave part*/ ) map function select ( i : natural; bundle b : master(bundle_array_t) ) to master(bundle_t) is map ( a => b(i).a, b => b(i).b, ); end map function select; begin for_gen : for i in bnd_array'range generate b_arr(i) <= (clk => clk, others => new); end generate generate_label; intst : component c port map( clk => clk, rst => rst, bundle_v1 => bundle_v, bundle_v2 => (bundle_v.a, bundle_v.b), bundle_v3 => select(1, bundle_v), bundle_ar => bundle_ar ); end architecture top;</verbatim> ---+++ Map functions (optional) Elaboration-time functions that help mapping signals & bundles to another bundle Used to avoid nested mapping (map ( x => y map (...) ) Reusable & improves readability: (example select_slave(i, master_bus)) <verbatim>map function mapper ( signal clk : in std_logic; constant c : natural; bundle bnd1 : master(bundle_t_1); bundle bnd2 : slave(bundle_t_2); ) to master(bundle_t_3) is map ( clk => clk, foo => bnd1.foo, baz => bnd2.baz ); end map function mapper;</verbatim> ---++ Changes to LRM This is a placeholder, haven't looked these up yet, the grammar rules are from memory :) * New keywords * *bundle* * *modport* * New *_declarative_items (package, entity, architecture, ..?) * bundle_type_declaration * bundle_declaration * modport_declaration * map_function * Modified grammar rules * _port_ _interface_list * _parameter_ _interface_list * a new primary rule '*new*' to support (*others* => *new*) * Type system changes * a new type 'bundle' * part of composite types? * can't be part of a record, protected and access type ---++ Reflection Identified 3 more or less orthogonal work areas: 1 The type * heterogenious data or homogenious data (records) * Options * We create a new kind of type: bundle * a lot of duplication between record & bundle: as a good engineer I hate special cases * weird interaction with records: bundles can't be part of a record * requires new kind of data "bundle b : bundle_t := (...)" * do *we really need this* data container? * where does it fit in the type classification? Container or something else? * We change the definition of records * signal foo : record_type => what does this mean when record_type contains signals & variables? * Split this off in another proposal 1 The modport * Creates a port structure from a composite type like record or an array of records * Only applies to ports (signals): sortof clashes with bundles * Uses a record or bundle as a template, the result is an "exploded" record, you can't go back to the underlying record * Clean solution: reuse existing types * How do we encode assignability between modports? * some modports are directly compatible, for example assign to a modport with only "in" elements * How do we apply a modport * modport(record_t) * record_t.modport * record_t'modport * <modport> record_t * keyword(modport) record_t * bundle some_name : modport record_t -- looking at the whole declaration bundle requires modport 1 The mapping * Convert one modport into another, without introducing delta cycles * do type conversions * apply selected names * check access rules * Necessary to avoid nested mapping in instantiations ---++ Use Cases ---++ Arguments FOR ---++ Arguments AGAINST ---++ General Comments <br /><span data-mce-mark="1"> I think the idea of separating modports from the heterogeneity requirement of bundles makes a lot of sense, and I think I'll just talk about modports for the moment, and for the sake of argument it'll be modports on records of signals, which I think is the dominant use case. We're currently asking modports to perform two different jobs; direction and adaptation. Let's talk first only about direction; all signals in the record go from in to out. In this case, the "record of signals" is akin to a bunch of wires, and the record structure is nothing more than a zip tie around those wires. If all a modport is asked to do is direction, then it's the equivalent of a keyed connector. The male connector goes on the record, the female on a bulkhead on the entity, and now you can only connect the record to the entity in a single "way" (these are in, those are out). Inside the entity you've just got the solder tails of the connector; they're just signals again. If all you had was direction, you could handle adaptation with entities. They'd have two bulkhead connectors on the entity, one that fit one type of record and one that fit another. Nothing would inherently relate the two record types, you've just plugged in an adapter between the two cable bundles. (Ignore the delta cycle issue). So now you expand the concept of a modport. It's not just a keyed connector (which is itself a physical entity). It's a keyed connector that may have some wiring inside, it moves some signals around and leaves some others out. And it can be bulkhead mounted, so you can put it directly on the sidewall of another entity and get one (keyed) record type on the outside of the entity, and solder tails for a different record type on the inside. -- %BUBBLESIG{RobGaddi - 2016-04-28}% %COMMENT%</span> ---++ Supporters -- <span data-mce-mark="1">%USERSIG{LievenLemiengre - 2016-04-12}%</span>
E
dit
|
A
ttach
|
P
rint version
|
H
istory
: r9
<
r8
<
r7
<
r6
<
r5
|
B
acklinks
|
V
iew topic
|
Ra
w
edit
|
M
ore topic actions
Topic revision: r9 - 2016-04-28 - 18:00:32 -
RobGaddi
P1076
Log In
or
Register
P1076 Web
Create New Topic
Index
Search
Changes
Notifications
RSS Feed
Statistics
Preferences
Webs
Main
P1076
Ballots
LCS2016_080
P10761
P1647
P16661
P1685
P1734
P1735
P1778
P1800
P1801
Sandbox
TWiki
VIP
VerilogAMS
Copyright © 2008-2025 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki?
Send feedback