Design libraries and v2cc ------------------------- v2cc does not have a opaque notion of design libraries. VHDL files are not pre-analyzed and checked into some library data base. Instead, whenever a reference to a design unit needs to be made, v2cc parses the VHDL code of that design unit from fresh. Therefore, it needs to be able to find the source file of a design unit given the VHDL name of that unit. Thus, as far as v2cc is concerned, a design library is a mapping from VHDL identifiers to file names. There is also a mapping for getting library names from mapping files. Such a mapping is specified via a "mapping file". It contains a list of pattern rules that each transform a certain class of identifiers into file names. The syntax of a mapping file is: Lexical: litchar: 'a'..'z' | 'A'..'Z' | '0'..'9' | '_' | '/' | '-' | '.' escchar escchar: '\' char whitespace: ' ' | '\n' | '\v' | '\t' | comment comment: '#' any_character* '\n' opchar: ':' | ',' | '(' | ')' specchar: every printable char except litchar, whitespace and opchar symchar: litchar | specchar symbol: symchar+ Grammar: mapping: version patternrule* version: "v2cc_mapfile" "0" patternrule: symbol [ ':' symbol ] Comments are ignored. A mapping files specifies a sequence of pattern rules. When transforming an indentifier, each rule is tried in turn and the first one that matches is choosen. A rule looks like pattern: filename When the ": filename" part is omitted, it defaults to "patternEXT" where "EXT" is determined by the user of the mapping file. The "pattern" can contain the special character "<" which introduces a `wildcard'. The "<" must be followed by a ">", with arbitrary characters inbetween. These characters form the name of the wildcard. A wildcard matches any sequence of characters. There can be any number of wildcards in the pattern, but each must have a unique name. The "filename" can also contain the character "<", followed by a name, followed by ">". There, it introduces a `wildcard substitution'. It will be replaced with the characters that matched the wildcard with the same name in "pattern". When there is no wildcard in "pattern" with the right name, it will be replaced with nothing. While doing this replacement, the characters "#" and "/" are replaced as "##", and "#-" respectively. No other character translations are done, so if you have funny characters in your VHDL identifiers, you will have funny characters in your filenames. Before doing the comparison with the patterns, the VHDL identifier is brought into a canononical form: when it is not an abstract identifier, all its characters are down-cased. When the resulting filename is relative (does not begin with "/"), it is prefixed with the directory of the mapping file. A non-existent mapping file is equivalent to the single rule <> An empty mapping file is just that: an empty mapping. The mapping does not need to be reversible. It is OK when multiple identifiers map to a single filename. No special character besides "<" and ">" is valid in "pattern" or "filename". They are reserved for future extensions. The mapping files for going from design unit names to filenames are found by looking into directories specified by the `v2cc library path'. You can use the environment variable V2CC_LIBRARY_PATH and command line options to define the path. When the environment variable is not set, it defaults to a value that makes the standard libraries available that are distributed and installed with v2cc itself. When it is set, it completely overwrites this default value. The variable V2CC_LIBRARY_PATH consists of ":" separated filenames. The filename "*" is replaced with the default value mentioned above. In addition to the environment variable, you can use the "-L libdir" command line option with v2cc. The directories specified with "-L" are added in front of the ones specified by V2CC_LIBRARY_PATH. In the final library path, they appear in the same order as on the command line. Looking for a design unit named UNIT in a library named LIB is done like this: for each component of the library path, L if L is a regular file set LMAP to L else if L is a directory set LMAP to L/v2cc.libs else continue with next component translate LIB into FLIB using LMAP with EXT="" if FLIB.vhdl exists terminate with FLIB.vhdl as the result if FLIB.v2cc exists set UMAP to FLIB.v2cc else if FLIB is a directory set UMAP to FLIB/v2cc.units else continue with next component translate UNIT into FUNIT using UMAP with EXT=".vhdl" terminate with FUNIT as the result terminate unsuccessfully This mechanism is used for all design units that are referenced from within VHDL code (or via other means). There is a complication with architectures and package bodies, though, because they are not uniquely identified by a single identifier. For them, a artifical identifier is constructed. Architectures get names of the form <entity>(<architecture>) while package bodies become <package>(body) For example, "architecture struct of model" is turned into "model(struct)" and "package body misc" is turned into "misc(body)". When a design file contains multiple design units, they are all parsed, checked for correctnes and remembered, but only the needed unit will be used for code generation. That is, when a design file contains both a package header and a package body and the package header is referenced from another design unit, no code will be generated for the package body. When one of the ignored units will be referenced later in the same invocation of v2cc, the design file will not be read again because all design units are retained in core. Examples -------- The simplest situation is when you have no mapping files at all. A design library is then a directory on your library path. The name of that directory is that of the library in VHDL. Each file in that directory with a ".vhdl" extension is used for a design unit with the same name as the file without the extension. Say you have this directory structure somedir/ std/ standard.vhdl textio.vhdl ieee/ numeric_bit.vhdl std_logic_1164.vhdl When you put "somedir" into your library path, you have access to the design units STD.STANDARD STD.TEXTIO IEEE.NUMERIC_BIT IEEE.STD_LOGIC_1164 In this situation, you have one file per design unit. When you have one file per design library, it would look like this somedir/ fmf.vhdl All references to design units in the FMF design library would be routed to "fmf.vhdl". Considerations -------------- - Simplicity The mapping is intended to be simple. If you find yourself doing complicated things or wanting complicated extensions, we should probably rethink the mapping file completely. Maybe it is better to be able to specify an external program that gets called to do the mapping. - Extensibility Simple things within the pattern rules can be done by defining a meaning for other special characters. Broader changes to the grammar of the file should be marked with a different version number, or maybe even a different format name. - Efficiency It might be that the repeated parsing of VHDL source code will be an unduly overhead. This might not really be the case (Edwin says the C++ compiler takes much longer anyway), but if it turns out to be a problem, the solution would be to cache the results of previous parsing runs on disk. This should be done transparent to the user (although the user should of course be able to detect and correct problems with the caching like full disks or denied write permission to the caching directoy). - Automatic generation Mapping files are meant to be written by hand. If you are thinking about some automatic mechanism by which to generate them, it is probably better to extend the capabilities of the mapping files so that your new mechanism can be selected.