Rule Selection
This section will detail the guidelines followed for creating and organizing rules.
Note
VSG can not fully classify a VHDL file, this will place limitations on the ability to write rules.
Goals
The VHDL Language Reference Manual (LRM) will be the basis used when determining rule creation, naming and the organization of rules.
Guidelines
[naming_001] Rule naming shall be of the form
{identifier}_{number}
.[naming_002] The identifier shall be the left-hand side of VHDL production.
[naming_003] The number shall be three digits.
[naming_004] The rule number shall indicate which phase the rule is executed in.
[naming_005] An identifier and number pair shall never be re-used.
[scoping_001] Rules shall be scoped to a VHDL production
Example
The following production shows the structure of an architecture.
architecture_body ::=
*architecture* identifier *of* entity_name *is*
architecture_declarative_part
*begin*
architecture_statement_part
*end* [ *architecture* ] [ architecture_simple_name ] ;
The VHDL keywords are enclosed with asterisks, architecture
, of
, is
, begin
and end
.
Everything else is another production:
identifier ::=
basic_identifier | extended_identifier
name ::=
simple_name
| operator_symbol
| character_literal
| selected_name
| indexed_name
| slice_name
| attribute_name
| external_name
architecture_declarative_part ::=
{ block_declarative_item }
architecture_statement_part ::=
{ concurrent_statement }
Rules targeting the architecture_body
will only include those elements at that level of the production.
For example:
architecture_body_100 = architecture on its own line
architecture_body_101 = identifier on same line as architecture
architecture_body_102 = of on same line as identifier
architecture_body_103 = entity_name on same line as of keyword
architecture_body_104 = is on same line as entity_name
architecture_body_105 = no code after is keyword
architecture_body_106 = begin on its own line
architecture_body_107 = no code after begin keyword
architecture_body_108 = end on its own line
architecture_body_109 = architecture on same line as end
architecture_body_110 = architecture_simple_name on same line as end
architecture_body_111 = semicolon on same line as end
architecture_body_112 = no code after semicolon
architecture_body_120 = add/remove optional keyword architecture
architecture_body_121 = add/remove optional architecture_simple_name
architecture_body_200 = whitespace between architecture and identifier
architecture_body_201 = whitespace between identifier and of keyword
architecture_body_202 = whitespace between of and entity_name
architecture_body_203 = whitespace between entity_name and is keyword
architecture_body_204 = whitespace between end and architecture keyword
architecture_body_205 = whitespace between architecture and architecture_simple_name
architecture_body_206 = whitespace between architecture_simple_name and semicolon
architecture_body_400 = indent of architecture keyword
architecture_body_401 = indent of begin keyword
architecture_body_402 = indent of end keyword
architecture_body_600 = case of architecture keyword
architecture_body_601 = case of identifier
architecture_body_602 = case of of keyword
architecture_body_603 = case of entity_name
architecture_body_604 = case of is keyword
architecture_body_605 = case of begin keyword
architecture_body_606 = case of end keyword
architecture_body_607 = case of ending architecture keyword
architecture_body_608 = case of architecture_simple_name
architecture_body_700 = naming restrictions on identifier and architecture_simple_name
One question to answer are blank lines.
Are they part of architecture_body
or the next production?
Expanding the architecture_declarative_part
production shows:
block_declarative_item ::=
subprogram_declaration
| subprogram_body
| subprogram_instantiation_declaration
| package_declaration
| package_body
| package_instantiation_declaration
| type_declaration
| subtype_declaration
| constant_declaration
| signal_declaration
| shared_variable_declaration
| file_declaration
| alias_declaration
| component_declaration
| attribute_declaration
| attribute_specification
| configuration_specification
| disconnection_specification
| use_clause
| group_template_declaration
| group_declaration
| PSL_Property_Declaration
| PSL_Sequence_Declaration
| PSL_Clock_Declaration
Vertical spacing between these elements will be performed by rules in the block_declarative_part
group.
This will eliminate the issue where multiple blank line rules could collide.
block_declarative_part_300 = blank line at beginning of block_declarative part
block_declarative_part_301 = blank line at end of block_declarative part
block_declarative_part_302 = blank line before block_declarative_item (could be configurable) (could also conflict with block_declarative_item_001)
etc…
The block_declarative_part can include from 0 to N block_declarative_items. Alignment rules between block_declarative_items, e.g. colon alignment in signal_declaration and constant_declaration, will also be performed at this level.
block_declarative_part_500 = align identifiers in file, constant and signal declarations
block_declarative_part_501 = align : in constant and signal declarations
etc…
Other structural rules could be created:
block_declarative_part_100 = all constants defined at top of block_declarative_part (maybe this is out of scope of VSG though)
Taking the next step down to the signal_declaration level:
signal_declaration ::=
signal identifier_list : subtype_indication [ signal_kind ] [ := expression ] ;
The following rules would be generated:
signal_declaration_100 = signal keyword on its own line
signal_declaration_101 = identifier_list on same line as signal keyword
signal_declaration_102 = colon on same line as identifier_list
signal_declaration_103 = subtype_indication on same line as colon
signal_declaration_104 = signal_kind on same line as subtype_indication
signal_declaration_105 = := on same line as signal_kind
signal_declaration_106 = expression on same line as :=
signal_declaration_107 = semicolon on same line as expression
signal_declaration_108 = no code after semicolon
signal_declaration_200 = whitespace between signal keyword and identifier_list
signal_declaration_200 = whitespace between identifier_list and colon
signal_declaration_200 = whitespace between colon and subtype_indication
signal_declaration_200 = whitespace between subtype_indication and signal_kind
signal_declaration_200 = whitespace between signal_kind and :=
signal_declaration_200 = whitespace between := and expression
signal_declaration_400 = indent of signal keyword
signal_declaration_600 = case of signal keyword
signal_declaration_601 = case of identifiers in identifier_list
signal_declaration_700 = naming restrictions on signal identifiers
One could argue rule 601 should be moved to an identifier_list set of rules, but it seems appropriate at this level.
identifier_list ::=
identifier { , identifier }
I would make the argument that signal_kind case would be done by a signal_kind rule.
signal_kind ::=
register | bus
One could make the argument that subtype_indication should be handled by its own set of rules:
subtype_indication ::=
[ resolution_indication ] type_mark [ constraint ]
resolution_indication ::=
resolution_function_name | ( element_resolution )
element_resolution ::= array_element_resolution | record_resolution
type_mark ::=
type_name | subtype_name
And the same for constraint:
constraint ::=
range_constraint
| array_constraint
| record_constraint
If the subtype_indication and constraint rules were moved out of signal_declaration, and where ever else they are located, that it would reduce the number of rules. VSG currently uses a base rule to handle constraints, which is extended where constraints are used.