|
| 1 | +// This Source Code Form is subject to the terms of the Mozilla Public |
| 2 | +// License, v. 2.0. If a copy of the MPL was not distributed with this file, |
| 3 | +// You can obtain one at http://mozilla.org/MPL/2.0/. |
| 4 | +// |
| 5 | +// Copyright (c) 2026, Lukas Scheller lukasscheller@icloud.com |
| 6 | + |
| 7 | +//! This example uses the builder-API to show how to programatically create a testbench entity. |
| 8 | +//! The builder-API is feature-complete, but may not be ergonomic for common cases such as |
| 9 | +//! testbench generation. |
| 10 | +use vhdl_syntax::syntax::{ |
| 11 | + builders::*, AstNode, LibraryUnitSyntax, NameDesignatorToken, NamePrefixSyntax, |
| 12 | + PrimaryUnitSyntax, SecondaryUnitSyntax, |
| 13 | +}; |
| 14 | + |
| 15 | +fn main() { |
| 16 | + // The builder API is used to programaticall build VHDL nodes. |
| 17 | + // Each SyntaxNode has an associated Builder Node. E.g., `EntityDeclarationSyntax` -> `EntityDeclarationBuilder`. |
| 18 | + // The constructor takes all required nodes and entities. |
| 19 | + // required keywords and nodes are auto-generated, but you may change them using `.with_*(token)` methods. |
| 20 | + |
| 21 | + // An entity declaration syntax is split into multiple nodes, the most important being |
| 22 | + // the preamble ("entity foo is"), the declarations, concurrent statements and the epilogue ("end entity foo;"). |
| 23 | + // Consult the EntityDeclarationSyntax struct for more information. |
| 24 | + // Of all these nodes, only the PreambleSyntax must be provided. The remaining nodes are either optional, |
| 25 | + // repeated or tokens (which will be default-initialized). |
| 26 | + // An entity as defined above will produce the VHDL code ` entity tb_foo is end ;` |
| 27 | + let mut builder = EntityDeclarationBuilder::new(EntityDeclarationPreambleBuilder::new(b"foo")); |
| 28 | + // In order to repeat the second identifier, we overwrite the default-generated `EntityDeclarationEpilogue` |
| 29 | + // and provide the name. The new epilogue is equally generated through a builder. |
| 30 | + builder = builder.with_entity_declaration_epilogue( |
| 31 | + EntityDeclarationEpilogueBuilder::new().with_identifier_token(b"foo"), |
| 32 | + ); |
| 33 | + // transform the builder into syntax by calling `build()` on it |
| 34 | + let entity_declaration_node = builder.build(); |
| 35 | + |
| 36 | + // Names are highly complicated in VHDL and so is building them. |
| 37 | + // The ergonomics of this may change in the future, but currently this is the only way to build names. |
| 38 | + // `NameDesignatorToken::identifier` creates a token-choice wrapper from a plain identifier. |
| 39 | + let entity_name = NameBuilder::new(NamePrefixSyntax::NameDesignatorPrefix( |
| 40 | + NameDesignatorPrefixBuilder::new(NameDesignatorToken::identifier(b"foo")).build(), |
| 41 | + )); |
| 42 | + |
| 43 | + // Create an architecture syntax. |
| 44 | + let architecture_syntax = |
| 45 | + ArchitectureBodyBuilder::new(ArchitecturePreambleBuilder::new(b"arch", entity_name)) |
| 46 | + .build(); |
| 47 | + |
| 48 | + // build the VHDL file with entity and architecture |
| 49 | + let file = DesignFileBuilder::new() |
| 50 | + .add_design_units(DesignUnitBuilder::new(LibraryUnitSyntax::PrimaryUnit( |
| 51 | + PrimaryUnitSyntax::EntityDeclaration(entity_declaration_node), |
| 52 | + ))) |
| 53 | + .add_design_units(DesignUnitBuilder::new(LibraryUnitSyntax::SecondaryUnit( |
| 54 | + SecondaryUnitSyntax::ArchitectureBody(architecture_syntax), |
| 55 | + ))) |
| 56 | + .build(); |
| 57 | + |
| 58 | + // The canonical output consists of tokens separated by a single space. |
| 59 | + // Formatters can be used to nicely display this to the user. |
| 60 | + assert_eq!( |
| 61 | + file.raw().to_string(), |
| 62 | + " entity foo is end foo ; architecture arch of foo is begin end ; " |
| 63 | + ) |
| 64 | +} |
0 commit comments