V2CC.LIBS(5)

πŸ“¦ version 0.0.8, in arch rolling

πŸ’– v2cc.libs β€” the VHDL library mapping file for the FreeHDL compiler/simulator πŸ’–

okay so bestie, this is section 5 of the manual (file formats, iykyk) and it's literally the whole tea on how FreeHDL figures out which file your design unit lives in. no cap, it's more interesting than it sounds. pull up a chair 🫢


✨ DESCRIPTION ✨

So. FreeHDL is a compiler/simulator suite for the hardware description language VHDL, and it's got your back for both VHDL'93 and VHDL'87 standards. slay.

Here's the vibe: FreeHDL translates the original VHDL source FILEs into C++. then that C++ source gets compiled and linked to the kernel to build the simulation program. starting the generated executable will simulate the corresponding VHDL model. the actual build process to generate the simulator from the VHDL source is, and I cannot stress this enough, a complex process, and it's all handled by the gvhdl script. main character energy tbh πŸ‘‘

Now the important part. FreeHDL does not have an opaque notion of design libraries. like, at all. VHDL files are not pre-analyzed and checked into some library data base like in other VHDL compiler/simulator systems. instead β€” and this is the iconic bit β€” whenever a reference to a design unit needs to be made, FreeHDL parses the VHDL code of that design unit from fresh. from scratch. every time. so it needs to be able to find the source file of a design unit given the VHDL name of that unit.

So, as far as FreeHDL is concerned:

a design library is literally just a mapping from VHDL identifiers to file names πŸ’…

There's also a mapping for getting library names from mapping files. and that whole thing is specified via a "mapping file", which contains a list of pattern rules that each transform a certain class of identifiers into file names.

🌸 the syntax of a mapping file

the lexical bit

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+

the grammar bit

mapping: version patternrule*

version: "v2cc_mapfile" "0"

patternrule: symbol [ ':' symbol ]

Comments are ignored. (free therapy, honestly 🧚)


A mapping file specifies a sequence of pattern rules. when transforming an identifier, each rule is tried in turn and the first one that matches is chosen. first come first served, periodt.

πŸŽ€ the rules themselves

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. cute, right?

The pattern can contain the special character < which introduces a wildcard. the < must be followed by a >, with arbitrary characters inbetween. those inbetween 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. no duplicates bestie, we don't do that here πŸ™ˆ

The filename can also contain the character <, followed by a name, followed by >. there, it introduces a wildcard substitution β€” it gets replaced with the characters that matched the wildcard with the same name in pattern. when there's no wildcard in pattern with the right name, it will be replaced with nothing. (ghosted. πŸ’€)

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. fr fr, that's a you problem, not a FreeHDL problem 😭


πŸ¦‹ canonical form & paths

Before doing the comparison with the patterns, the VHDL identifier is brought into a canonical form: when it is not an abstract identifier, all its characters are down-cased. (lowercase era.)

When the resulting filename is relative β€” meaning it 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. that's it. that's the whole thing. ✨

The mapping does not need to be reversible. it is totally OK when multiple identifiers map to a single filename. no jealousy, no drama.

⭐ heads up: no special character besides < and > is valid in pattern or filename. They are reserved for future extensions. so don't get creative, bestie β€” the future called dibs.

πŸ’œ the v2cc library path

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. whole thing. gone. replaced. πŸ’…

V2CC_LIBRARY_PATH consists of ":" separated filenames. the filename "*" is replaced with the default value mentioned above. (little asterisk, big power.)

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. and in the final library path, they appear in the same order as on the command line. order matters, bestie 🫢


πŸ”₯ looking up a design unit (the actual algorithm)

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).

😭 the architecture / package body complication

There is, unfortunately, a complication with architectures and package bodies, because they are not uniquely identified by a single identifier. for them, an artificial 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)". iconic little rename, ngl.


🌈 multiple design units in one file

When a design file contains multiple design units, they are all parsed, checked for correctness 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. and 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. efficiency queen πŸŽ€


🌸 EXAMPLES 🌸

the simplest situation: no mapping files at all

A design library is then just 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. so simple. so clean. we love her.

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". one file carrying the whole library on its back. legend behaviour πŸ‘‘


the /foo example

As another example, assume that all VHDL libraries are mapped into subdirs starting from root directory "/foo". further, assume that there are VHDL libraries named "lib1" and "lib2". they shall be mapped to subdir "/foo/lib1_dir" and "/foo/lib2_dir". hence, the file/directory structure is as follows:

/foo                <-  library root directory
/foo/v2cc.libs      <-  mapping control file
/foo/lib1_dir       <-  library dir for VHDL library lib1
/foo/lib1_dir/comp1.vhdl <- file that contains VHDL model comp1
/foo/lib2_dir       <-  library dir for VHDL library lib2
/foo/lib2_dir/comp2.vhdl <- file that contains VHDL model comp2

Then, file "/foo/v2cc.libs" should contain:

v2cc_mapfile 0 lib1 : lib1_dir lib2 : lib2_dir

In order to compile a design named comp1 (stored in file comp1.vhdl) into VHDL library lib1, goto subdir "/foo/lib1_dir" and execute:

gvhdl -c -L .. -l lib1 comp1.vhdl
πŸ’‘ note that option -l lib1 forces the compiler to associate the model stored in "comp1.vhdl" with VHDL library lib1. note further, that the compiler switch -L .. specifies the path to the directory where "v2cc.libs" is stored.

You may also specify an absolute path:

gvhdl -c -L /foo -l lib1 comp1.vhdl

Note that comp1 should reside in a file named "comp1.vhdl". (name your files properly, bestie, please 😭)

If lib2 contains a design comp2 that makes use of comp1 from lib1, then goto "/foo/lib2_dir" and run the following command to create an executable for model comp2:

gvhdl -L .. -l lib2 comp2.vhdl ../lib1_dir/comp1.o

πŸ¦‹ SEE ALSO πŸ¦‹


⭐ AVAILABILITY ⭐

The latest version of FreeHDL can always be obtained from www.freehdl.seul.org β€” go get her πŸ’–


πŸ’€ REPORTING BUGS πŸ’€

Known bugs are documented within the BUGS file. so check there first, bestie, before you come for anybody 🫢

  • If your report addresses a parser related topic, contact Marius Vollmer <mvo@zagadka.ping.de>.
  • If it is related to the code generator or compiler, send an email to Edwin Naroska <edwin@ds.e-technik.uni-dortmund.de>.
  • If you are not sure, send it to Edwin. he will take care of forwarding your report to the appropriate recipient. (he's the group chat admin of bug reports, lowkey πŸ‘‘)

Edwin Naroska Β© 1999, 2000, 2001, 2002, 2003, 2004, 2005 <edwin@ds.e-technik.uni-dortmund.de>

This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

read that again. NO WARRANTY. not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. protect yourself, bestie πŸ’…

🌈 AUTHORS 🌈

Written by Marius Vollmer <mvo@zagadka.ping.de> and Edwin Naroska <edwin@ds.e-technik.uni-dortmund.de>.


and that's the whole page, bestie ✨ this one shipped out on Debian/GNU Linux back in December 2005, and it's still out here explaining mapping files with zero notes. go off, vintage documentation πŸ’–πŸŽ€πŸ¦‹

πŸ“¦ where this page comes from