VisualDCT EPICS Databases Hierarchy Support | |
---|---|
Project: | VisualDCT |
Classification: | Design Document |
Identification: | CSL-DES-02-XX |
Copyright © 2002 by Cosylab Ltd. All Rights Reserved. |
Revision | Date | Author | Section | Modification |
---|---|---|---|---|
1.0 | 2002-08-20 | Matej Sekoranja | ||
all | Created from the document written by A. Johnson and J. Maclean. |
The document is based on discussion between Andrew Johnson, John Maclean and Matej Sekoranja.
This document is classified as a public document. Redistribution and use, with or without modification, are permitted provided that:
ID | Author | Reference | Revision | Date | Publisher |
---|---|---|---|---|---|
1 | Matej Sekoranja | VisualDCT Project | 2002 | Cosylab, Ltd. |
This document's meta-information (authors, revision history, table of contents, ...) can be found above. What follows below is the body of the document. The body is composed of several sections, which may be further composed of subsections.
Typographical styles are used to denote entities of different kinds. For a full list of entities and their respective typographic conventions, please refer to the Styles section of the XML Documentation document.
When viewing the document in a non-printed form, it is possible to submit comments regarding a given section to the document's owner. This is achieved by clicking the mail icon next to the section title. For this to work, your mail must be configured to properly handle the mailto URLs.
The current EPICS template substitution mechanism is very restricted in its capabilities. It requires two input files (.template and .substitutions) that have radically different syntaxes, and it only allows macros to be passed downwards into a template instance. Hierarchical templates as implemented by VisualDCT must allow macro values to be passed into the template instance (giving values for fields within the expanded template), and values to be exported from the template instance to the higher level (usually the destination field name for a link in a record defined in the higher level .vdb file).
We propose adding two statements to the database file format and modifying the macro naming syntax slightly to implement true hierarchical behaviour. Macros are defined in an expand statement and pass information into a template; ports are a kind of macro defined in a template statement that pass information upwards out of a template instance to their calling database. Here's an example of a top-level file using the proposed syntax:
record(calc,"slide1:error") { field(INPA, "$(slmot1.position)") ... } expand("slideMotor.vdb", slmot1) { macro(name, "sm1") macro(address, "4") macro(demand, "slide1:demand.VAL") } record(ao,"slide1:speed") { field(OUTP, "$(slmot1.speed)") field(DTYP, "Soft Channel") ... }
Listing 1: Simple database with new expansion syntax.
Note that we're using the macro syntax $(template_instance_name.port_name) to bring port values from the template instance into the higher level diagram. Unfortunately we have to allow port macros to be used before the related expand statement appears in the parent .vdb file, so the database flattening tool will have to make two passes through the data and should also detect loops in port/macro definitions.
When performing macro substitutions within strings, if a macro name is undefined the macro name and its surrounding $() characters will be left unchanged in the flat .db file. This allows templates to be used when creating a database that still takes macro arguments on loading with dbLoadRecords(). For undefined port macros though an error should probably be reported instead (but remember that these can't be properly checked and substituted until all expand statements and their related templates have been read in).
Inside the template file slideMotor.vdb, we can define ports using the new template statement. Ports are usually going to contain record.field names, but they can be literal strings and may use macros in their value:
template("Description of the Slide Motor template...") { port(speed, "$(name):speed.VAL", "Record to set motor speed mm/sec") port(go, "$(name):startmoving", "Forward link to this to cause movement") port(position, "$(motor.position)", "Current position of the slide") port(greet, "Hello, world!", "Just being friendly...") } record(ai, "$(name):speed") { ... } record(ai, "$(name):dest") { field(INP, "$(demand)") ... } record(calc, "$(name):startmoving") { ... } expand("motor.vdb", motor) { macro(address, "$(address)") ... }
Listing 2: slideMotor.vdb database with new template block.
Note that a template statement is optional; if a template file doesn't need to export any data to its parent it doesn't have to have one. The string argument provides a place for the user to put some descriptive text. Multiple template statements are allowed, although only the first description string will be used. If a port name is repeated either within a single template statement or in subsequent ones, only the first definition is used - later redefinitions will be ignored. An empty template statement may also be used if desired to document this database as a template, and would look like this (the parentheses and braces are required if the template keyword is present):
template () {}
Similarly an expand statement doesn't have to define any macros, but the braces are still mandatory:
expand ("subsys.vdb", ss) {}
There are a couple of interesting and subtle differences between the above empty expand statemend and the statement:
include "subsys.vdb"
There may be circumstances where a template designer might use an include statement rather than an expand statement. If the subsys.vdb file defines some port values for the parent to use, the expand statement makes those port values available within this .db file as $(ss.port_name). Using an include statement those port values will be made available to the parent .db file instead. Also an expand statement with no macro definitions will not pass any macro values to the subsys.vdb file, whereas by using an include statement the subsys.vdb file will have full access to all the macros defined by the parent for use in this .db file. Thus an include statement is useful where there are a collection of related templates that a designer wishes to combine into a single template without having to instantiate each one separately and pass a common set of macros into.
VisualDCT will be the first tool that is capable of flattening this new database hierarchy syntax (capFast designs have always had similar hierarchical template capabilities), although at least one other will be produced in Base R3.15 for use with gnumake. The flattening process involves expanding all templates and replacing the macro and port macro variables with their strings. If a macro name is found that has no definition within its scope, it will be left exactly as it was found, which allows load-time macros to be used. We also strongly recommend that flattening tools mark the beginning and end of each template file in the flat database file using a comment as follows, to provide a way for other tools to refer back to the original template from the flat file:
# expand("/full/path/to/template.vdb", instance_name) ... expanded contents of template.vdb # end (instance_name)
Listing 3: An example of flatten DB.
Note that templates that expand other sub-templates should nest as appropriate, but this implies that the flattening tool (Road-roller? Steam-iron?) must maintain the nesting properly in the output.
Space, tab and newline characters are permitted and ignored between most of the tokens below, other than inside a macro name or string.
? means the token preceeding is allowed 0 or 1 times * means the token preceeding is allowed 0 or more times + means the token preceeding is allowed 1 or more times .. signifies the end of a definition.
Listing 4: A short review of EBNFG.
macronamechar = [a-zA-Z0-9_:-] . macroname_definition = macronamechar+ | '"' macronamechar+ '"' . macro_expansion = '$(' macronamechar+ ')' . port_expansion = '$(' macronamechar+ '.' macronamechar+ ')' . string_element = [^"] | '\"' | macro_expansion | port_expansion . quotedstring = '"' string_element* '"' . string = macronamechar+ | quotedstring . noteol = [^\n] . comment = '#' noteol* . macro_definition = comment | ('macro' '(' macroname_definition ',' string ')') . expand = 'expand' '(' quotedstring ',' macroname_definition ')' '{' macro_definition* '}' . port_definition = comment | ('port' '(' macroname_definition ',' string ( ',' quotedstring)? ')') . template = 'template' '(' quotedstring? ')' '{' port_definition* '}' .
Listing 5: An EBNFG syntax of new keywords.
Download example DBs demonstrating hierarchical capabilities.