PSS 3.0 API Documentation

This document describes the API additions for PSS 3.0 support in pssparser.

AST Nodes for PSS 3.0

Monitor AST Nodes

Monitor

Represents a monitor declaration (Section 19 of PSS 3.0 spec).

Namespace: pssp::ast

Base Class: TypeScope

Properties:

  • is_abstract (bool) - Whether the monitor is abstract

  • super_type (ITypeRef) - The super type if the monitor extends another

  • monitors (list<IMonitor>) - Nested monitor declarations

  • activities (list<IMonitorActivityDecl>) - Monitor activity declarations

  • constraints (list<IConstraint>) - Monitor constraints

Python API:

from pssparser import ast

# Create a monitor
monitor = ast.Monitor("MyMonitor")
monitor.is_abstract = False

# Access properties
print(f"Monitor name: {monitor.name}")
print(f"Is abstract: {monitor.is_abstract}")

C++ API:

#include "pssp/ast/IMonitor.h"

// Access monitor properties
pssp::ast::IMonitor *monitor = /* ... */;
bool is_abstract = monitor->getIsAbstract();
const std::vector<ast::IMonitorUP> &monitors = monitor->getMonitors();

MonitorActivityDecl

Represents a monitor activity declaration.

Properties:

  • activity (IMonitorActivityStmt) - The activity statement

Usage:

from pssparser import ast

# Create activity declaration
activity_decl = ast.MonitorActivityDecl()

# Set activity statement
sequence = ast.MonitorActivitySequence()
activity_decl.activity = sequence

MonitorActivitySequence

Represents a sequence of monitor activities.

Properties:

  • activities (list<IMonitorActivityStmt>) - Sequential activities

Usage:

sequence = ast.MonitorActivitySequence()

# Add activities
sequence.activities.append(activity1)
sequence.activities.append(activity2)

MonitorActivityConcat

Represents temporal concatenation (concat blocks).

Properties:

  • activities (list<IMonitorActivityStmt>) - Activities to concatenate

Usage:

concat = ast.MonitorActivityConcat()
concat.activities.append(action_ref1)
concat.activities.append(action_ref2)

MonitorActivityEventually

Represents an eventually activity (must occur eventually).

Properties:

  • activity (IMonitorActivityStmt) - The activity that must occur

Usage:

eventually = ast.MonitorActivityEventually()
eventually.activity = sequence_activity

MonitorActivitySchedule

Represents unordered concurrent activities (schedule blocks).

Properties:

  • activities (list<IMonitorActivityStmt>) - Concurrent activities

Usage:

schedule = ast.MonitorActivitySchedule()
schedule.activities.append(activity1)
schedule.activities.append(activity2)

MonitorActivityActionTraversal

Represents traversal of an action in a monitor.

Properties:

  • action_ref (ITypeRef) - Reference to the action type

Usage:

traversal = ast.MonitorActivityActionTraversal()
# Set action reference
traversal.action_ref = action_type_ref

CoverStmt

Represents a cover statement.

Properties:

  • label (string) - Optional label for the cover statement

  • type_ref (ITypeRef) - Reference to the monitor type

  • variable_name (string) - Optional variable name for the cover instance

Usage:

cover = ast.CoverStmt()
cover.label = "my_coverage"
cover.type_ref = monitor_type_ref
cover.variable_name = "monitor_inst"

String Enhancement AST Nodes

StringMethodId

Enumeration of string methods (Section 7.6 of PSS 3.0 spec).

Values:

  • NoMethod - No method

  • Size - size() method

  • Find - find() method

  • FindLast - find_last() method

  • FindAll - find_all() method

  • Lower - lower() method

  • Upper - upper() method

  • Split - split() method

  • Chars - chars() method

Usage:

from pssparser.ast import StringMethodId

method = StringMethodId.Size
if method == StringMethodId.Find:
    print("Using find method")

ExprSubstring

Represents a substring operation (Section 7.6.2 of PSS 3.0 spec).

Properties:

  • target (IExpr) - The string expression

  • start (IExpr) - Start index (optional)

  • end (IExpr) - End index (optional)

Usage:

# s[0..4]
substring = ast.ExprSubstring()
substring.target = string_expr
substring.start = start_index_expr
substring.end = end_index_expr

# s[6..]
substring_open = ast.ExprSubstring()
substring_open.target = string_expr
substring_open.start = start_index_expr
# end is None

ExprMemberPathElem

Enhanced to support string methods.

Properties:

  • identifier (Identifier) - The member name

  • parameters (list<IExpr>) - Method parameters (if method call)

  • subscript (list<IExpr>) - Subscript expressions

  • string_method_id (StringMethodId) - String method identifier

Usage:

# s.size()
member = ast.ExprMemberPathElem()
member.identifier = "size"
member.string_method_id = ast.StringMethodId.Size

# s.find("world")
member = ast.ExprMemberPathElem()
member.identifier = "find"
member.string_method_id = ast.StringMethodId.Find
member.parameters.append(substring_expr)

Procedural Randomization AST Nodes

ProceduralStmtRandomize

Represents a procedural randomization statement (Section 16.6.6 of PSS 3.0 spec).

Properties:

  • target (ITemplateParamDeclValue) - The variable to randomize

  • constraint (IConstraint) - Optional inline constraint block

Usage:

randomize = ast.ProceduralStmtRandomize()
randomize.target = variable_ref

# With constraint
randomize.constraint = constraint_block

C++ API:

#include "pssp/ast/IProceduralStmtRandomize.h"

pssp::ast::IProceduralStmtRandomize *stmt = /* ... */;
ast::ITemplateParamDeclValue *target = stmt->getTarget();
ast::IConstraint *constraint = stmt->getConstraint();

Activity Atomic Block AST Nodes

ActivityAtomicBlock

Represents an atomic activity block (Section 22.6.7 of PSS 3.0 spec).

Properties:

  • activity (IActivityStmt) - The activity statement to execute atomically

Usage:

atomic = ast.ActivityAtomicBlock()
atomic.activity = activity_sequence

C++ API:

#include "pssp/ast/IActivityAtomicBlock.h"

pssp::ast::IActivityAtomicBlock *atomic = /* ... */;
ast::IActivityStmt *activity = atomic->getActivity();

Visitor API

The visitor API has been extended to support PSS 3.0 constructs.

C++ Visitor Interface

Header: src/AstBuilderInt.h

Monitor Visitors

class AstBuilderInt : public PSSParserBaseVisitor {
public:
    // Monitor declaration
    virtual antlrcpp::Any visitMonitor_declaration(
        PSSParser::Monitor_declarationContext *ctx) override;

    // Abstract monitor
    virtual antlrcpp::Any visitAbstract_monitor_declaration(
        PSSParser::Abstract_monitor_declarationContext *ctx) override;

    // Monitor activity
    virtual antlrcpp::Any visitMonitor_activity_declaration(
        PSSParser::Monitor_activity_declarationContext *ctx) override;

    // Activity statements
    virtual antlrcpp::Any visitMonitor_activity_sequence_block_stmt(
        PSSParser::Monitor_activity_sequence_block_stmtContext *ctx) override;

    virtual antlrcpp::Any visitMonitor_activity_concat_stmt(
        PSSParser::Monitor_activity_concat_stmtContext *ctx) override;

    virtual antlrcpp::Any visitMonitor_activity_eventually_stmt(
        PSSParser::Monitor_activity_eventually_stmtContext *ctx) override;

    virtual antlrcpp::Any visitMonitor_activity_schedule_stmt(
        PSSParser::Monitor_activity_schedule_stmtContext *ctx) override;

    // Cover statement
    virtual antlrcpp::Any visitCover_stmt(
        PSSParser::Cover_stmtContext *ctx) override;
};

Procedural Randomization Visitor

virtual antlrcpp::Any visitProcedural_randomization_stmt(
    PSSParser::Procedural_randomization_stmtContext *ctx) override;

Activity Atomic Block Visitor

virtual antlrcpp::Any visitActivity_atomic_block_stmt(
    PSSParser::Activity_atomic_block_stmtContext *ctx) override;

Python API Integration

Parser Class Extensions

The Parser class handles PSS 3.0 constructs transparently:

from pssparser import Parser

parser = Parser()

# Parse PSS 3.0 code
parser.parses([
    ("monitor.pss", """
        monitor MyMonitor {
            activity {
                concat {
                    A;
                    B;
                }
            }
        }

        component pss_top {
            action A { }
            action B { }

            cover MyMonitor;
        }
    """)
])

# Link and get AST
root = parser.link()

AST Traversal

PSS 3.0 nodes can be traversed like any AST nodes:

from pssparser import ast

def find_monitors(node):
    """Find all monitors in AST"""
    monitors = []

    if isinstance(node, ast.Monitor):
        monitors.append(node)

    # Traverse children
    for child in node.children:
        monitors.extend(find_monitors(child))

    return monitors

# Use with parsed AST
root = parser.link()
monitors = find_monitors(root)

for monitor in monitors:
    print(f"Found monitor: {monitor.name}")

Type Introspection

Check for PSS 3.0 types at runtime:

from pssparser import ast

def is_pss30_feature(node):
    """Check if node uses PSS 3.0 features"""
    return isinstance(node, (
        ast.Monitor,
        ast.MonitorActivityStmt,
        ast.ProceduralStmtRandomize,
        ast.ActivityAtomicBlock,
        ast.ExprSubstring
    ))

C++ API Usage Examples

Creating Monitor AST Programmatically

#include "pssp/ast/IFactory.h"
#include "pssp/ast/IMonitor.h"

// Get factory
ast::IFactory *factory = ast::getFactory();

// Create monitor
ast::IMonitorUP monitor = factory->mkMonitor("MyMonitor", false);

// Create activity declaration
ast::IMonitorActivityDeclUP activity_decl =
    factory->mkMonitorActivityDecl();

// Create sequence activity
ast::IMonitorActivitySequenceUP sequence =
    factory->mkMonitorActivitySequence();

// Set activity
activity_decl->setActivity(sequence.release());

// Add to monitor
monitor->getActivities().push_back(activity_decl.release());

Traversing Monitor Activities

#include "pssp/ast/IMonitor.h"

void processMonitor(ast::IMonitor *monitor) {
    // Process monitor properties
    std::string name = monitor->getName();
    bool is_abstract = monitor->getIsAbstract();

    // Process activities
    for (auto &activity_decl : monitor->getActivities()) {
        ast::IMonitorActivityStmt *activity =
            activity_decl->getActivity();

        // Check activity type
        if (auto *sequence =
            dynamic_cast<ast::IMonitorActivitySequence*>(activity)) {
            // Process sequence
            for (auto &stmt : sequence->getActivities()) {
                // Process each statement
            }
        }
    }
}

Best Practices

  1. Use Factory Methods: Create AST nodes via ast::getFactory()

  2. Check Node Types: Use dynamic_cast or isinstance before accessing type-specific properties

  3. Handle Null References: PSS 3.0 reference types can be null

  4. Validate Contexts: Check semantic rules (e.g., yield only in target exec)

Error Handling

Parse Errors

from pssparser import Parser

parser = Parser()

try:
    parser.parses([("file.pss", invalid_pss_code)])
except Exception as e:
    print(f"Parse error: {e}")

AST Validation

from pssparser import ast

def validate_monitor(monitor):
    """Validate monitor structure"""
    if not isinstance(monitor, ast.Monitor):
        raise ValueError("Not a monitor")

    if monitor.is_abstract and len(monitor.activities) == 0:
        print("Warning: Abstract monitor with no activities")

    # Additional validation...

Performance Considerations

  • AST Size: Monitor AST nodes add ~10% to AST size for typical models

  • Parse Time: PSS 3.0 constructs parse efficiently (< 5% overhead)

  • Memory: Monitor activities use minimal additional memory

  • Linking: Reference collections link as efficiently as standard collections

Thread Safety

The parser is not thread-safe. Use separate parser instances per thread:

from pssparser import Parser
import threading

def parse_in_thread(content):
    parser = Parser()  # New parser per thread
    parser.parses([("file.pss", content)])
    return parser.link()

threads = [
    threading.Thread(target=parse_in_thread, args=(content1,)),
    threading.Thread(target=parse_in_thread, args=(content2,))
]

Deprecations

No APIs are deprecated in PSS 3.0 support. All PSS 2.x APIs remain available.

See Also