UCLID5

repository·master·Indexed 41 days ago

https://github.com/uclid-org/uclid

An integrated tool for formal modeling, verification, and synthesis that utilizes SMT solvers to verify system properties and synthesize solutions. It supports LTL temporal operators, bit-vector arithmetic, and complex data types like records and enums. The tool integrates with solvers such as Z3, CVC5, and Delphi.

Tokens
7.2K
Snippets
19
Records
36
Agent score
100%

What's inside UCLID5

  1. UCLID5 Project Directory Structure

    master

    Understanding the repository layout:

    • examples/: Example UCLID5 models (including tutorial examples in examples/tutorial).
    • lib/: Dependencies (e.g., Z3).
    • project/: Build scripts.
    • src/main/scala/: UCLID5 source code.
    • src/test/scala/: UCLID5 test suite.
    • test/: Test programs for UCLID5.
    • tutorial/: UCLID5 tutorial (LaTeX source).
    • vim/: Vim syntax highlighting for UCLID5.
  2. Install prerequisites for UCLID5 on Linux

    master

    To use pre-built binaries on Linux, you need Z3 version 4.12.2 (with Java bindings) and OpenJDK (version 8, 9, 10, or 11).

    To simplify the installation of external solvers (Z3, CVC5, Delphi), run the provided setup scripts from the root of the UCLID5 repository. These scripts download the binaries and configure your PATH and LD_LIBRARY_PATH for the current session. To make these changes permanent, add the exported paths to your bash_profile.

    # Install Z3
    source get-z3-linux.sh
    
    # Install CVC5 (optional, for synthesis tests)
    source get-cvc5-linux.sh
    
    # Install Delphi (optional, for verification modulo oracles)
    source get-delphi-linux.sh
    
    # Example of permanent configuration in bash_profile
    export PATH=$PATH:/path/to/uclid/z3/bin:/path/to/uclid/cvc5/bin:/path/to/uclid/delphi/bin:/path/to/uclid/oracles
    export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/path/to/uclid/z3/bin
  3. Install UCLID5 using pre-built binaries

    master

    To use UCLID5 without compiling from source, download the latest release from the GitHub releases page. The executable uclid is located in the bin/ subdirectory of the downloaded package.

    # Download from https://github.com/uclid-org/uclid/releases
    # The binary is in the bin/ directory
    ./bin/uclid <your_model>.ucl
  4. Install prerequisites for UCLID5 on macOS

    master

    For macOS, it is recommended to use OpenJDK 11. You can install it via Homebrew. If you are on an older version of macOS, you may need to use homebrew/cask-versions.

    To install external solvers, run the macOS-specific setup scripts from the repository root.

    Note on System Integrity Protection (SIP): On some macOS versions, Java may ignore DYLD_LIBRARY_PATH. If you encounter issues, you may need to manually copy the JNI and non-JNI libraries to the system directories as shown in the installation guide.

    # Install OpenJDK 11
    brew install openjdk@11
    
    # Set Java 11 as default in .zshrc or .bash_profile
    export JAVA_11_HOME=$(/usr/libexec/java_home -v11)
    alias java11='export JAVA_HOME=$JAVA_11_HOME'
    java11
    
    # Install solvers
    source get-z3-macos.sh
    source get-cvc5-macos.sh
    source get-delphi-macos.sh
    
    # Fix for SIP (if necessary)
    cp /path/to/uclid/z3/bin/libz3.dylib /usr/local/lib
    cp /path/to/uclid/z3/bin/libz3java.dylib /Library/Java/Extensions
  5. Compile UCLID5 from source

    master

    To build UCLID5 from source, you need SBT (version 1.0 or greater) in addition to the standard prerequisites (Z3 with Java bindings and OpenJDK).

    Run the following command from the root directory to compile and test the project. If successful, you can create a universal package using sbt universal:packageBin.

    # Compile and test
    sbt update clean compile "set fork:=true" test
    
    # Create a universal package
    sbt universal:packageBin
    
    # Install the resulting package
    unzip uclid-0.9.5.zip
    cd uclid-0.9.5
    export PATH=$PATH:$PWD/bin
  6. Advanced UCLID5 model examples

    master

    Beyond the basic tutorial, the examples/ directory contains specialized models for security, hyperproperties, and hardware verification:

    • CPU Isolation: cpu_induction.ucl extends the Chapter 4 CPU model by adding an isolated mode of execution and proving non-interference between isolated and normal modes via induction.
    • Security (Setuid): setuid.ucl implements an automaton based on the paper Setuid Demystified (Chen, Wagen, and Dean, Usenix Security 2002). setuid_fixed.ucl provides a corrected version of this model.
    • Hyperproperties: two-safety.ucl demonstrates how to verify a 2-safety property using self-composition (based on Lee & Seshia, Chapter 17).
    • Processor Verification: simple-datapath.ucl demonstrates Burch-Dill style correspondence (refinement) checking, based on original UCLID research (Bryant, Lahiri, Seshia, CAV'02).
  7. Define Complex Types: Records, Tuples, and Enums

    master

    Beyond primitives, UCLID allows for structured data types:

    • Enums: Defined using enum { ID1, ID2, ... }. The default value is the first identifier in the list.
    • Tuples: An ordered collection of types, e.g., {int, boolean}. Fields are internally named _1, _2, etc.
    • Records: Named collections of fields with specific types, e.g., record { x: int, y: bool }.
    • Maps: Functions mapping input types to an output type, e.g., int * bool -> real.
    • Arrays: Collections of a specific type, e.g., [int * int] -> bool (an array of pairs mapping to a boolean).
  8. How VCD trace accumulation works

    master

    The VCD class acts as an accumulator for signal changes. It maintains an internal map of wires and valuesAtTime.

    • Wire Management: When wireChanged is called, the class checks if the wire exists. If not, it creates a new Wire object, assigns it a unique VCD ID using getIdString, and places it in the appropriate hierarchical Scope based on its dot-separated name (e.g., top.sub.signal).
    • Change Tracking: It only stores changes that represent a new value (isNewValue). This prevents the output file from being bloated with redundant data.
    • Hierarchical Scopes: The class supports a single top-level scope and automatically builds sub-scopes as you provide dot-separated wire names.
  9. How UCLID5 manages type synonyms and context

    master

    UCLID5 uses UclidSynonymMap and the ULContext object to manage the mapping between UCLID5 types and SMT-LIB2 types. This is critical when propagating information from SMT solvers (like counterexamples) back into the UCLID5 language.

    • UclidSynonymMap: A bidirectional map between Type and SynonymType (identifiers). It allows looking up a type by its name or finding the name associated with a specific type.
    • ULContext: A singleton that maintains the global context for type synonyms. It tracks:
      • origTypeMap: The original synonym map from the input .ucl file.
      • postTypeMap: The reconstructed type map from an SMT query or counterexample.

    ULContext provides utility methods to validate identifiers against the current context, such as checkEnum, checkField, and checkUninterpretedField.

  10. Understand the structure of a UCLID Module

    master

    In UCLID, a Module is the primary organizational unit. It consists of an id (Identifier), a list of declarations (decls), a list of generic proof commands (cmds), and a list of annotations (notes).

    Modules encapsulate various language constructs that define the behavior and interface of a component, including:

    • Variables: inputs, outputs, vars (state variables), and sharedVars.
    • Constants: constLits (numeric literals) and constants (declared constants).
    • Logic & Functions: functions, synthFunctions, and axioms.
    • Types: adts (Algebraic Data Types) and typeDeclarationMap.
    • Control Flow: An init block and a next block.
    • Imports/Instances: moduleImportDecls, funcImportDecls, and instances of other modules.
    • Macros & Defines: defines and macroDecls.

    The moduleType provides a summarized view of the module's interface, including its inputs, outputs, shared variables, constants, and function signatures.

  11. How AST nodes track position and identity

    master

    Every node in the UCLID5 Abstract Syntax Tree (AST) is part of a hierarchy that supports error reporting and unique identification.

    • ASTNode: The base trait for all elements in the AST. Every node is automatically assigned a unique integer ID via the IdGenerator.
    • PositionedNode: A trait that allows nodes to carry positional information (filename and line number).
    • ASTPosition: Represents the location of a node, consisting of an optional filename and a Scala Position object. It provides errorString() for generating human-readable error messages (e.g., "at file.ucl, line 10").
    • ASTNode.introducePos: A utility used during parsing to attach position information to nodes, ensuring that errors can be traced back to specific lines in the source code.
  12. VCD Data Structures: Wire, Change, and Scope

    master

    The VCD module uses three primary data structures to represent a simulation trace:

    • Wire: Represents a signal. It contains the name, a unique VCD id, the width in bits, and its hierarchical path.
    • Change: Represents a specific value held by a Wire. It includes logic to serialize values into VCD formats (e.g., binary b1010 for vectors or single bits for scalars).
    • Scope: Represents a module or hierarchical level. It contains a collection of wires and subScopes to build the tree structure required by the VCD format.