This project is a command-line Static Timing Analysis (STA) tool built in C++. It is designed as an educational tool to demonstrate key Object-Oriented Programming (OOP) principles, graph theory (DAGs), and fundamental Data Structures and Algorithms (DSA) as applied to digital circuit design.
The tool parses a text-based circuit netlist and a gate delay library. It then builds a graph representation of the circuit to perform timing analysis, identify the critical path, and report any timing violations.
- Circuit Parsing: Reads simple text-based netlists (
.txt) and gate delay libraries. - Graph-Based Architecture: Builds a Directed Acyclic Graph (DAG) to represent the circuit, where
Nodeobjects represent wires andGateobjects represent the connections and delays. - Object-Oriented Design: Uses polymorphism and a Factory Pattern to manage a wide variety of logic gates (AND, OR, NOT, XOR, Adders, MUXs).
- Core Timing Analysis:
- Forward Propagation: Calculates Arrival Times using a Topological Sort.
- Backward Propagation: Calculates Required Times using a reverse topological sort.
- Slack Calculation: Determines the timing margin (
Slack = RequiredTime - ArrivalTime) for every node.
- Critical Path Identification: Uses Depth-First Search (DFS) to find all paths and identifies the critical path(s) (those with the worst/lowest slack).
- Report Generation: Outputs a detailed timing report to the
reports/directory.
Static-Timing-Analysis/
├── src/ # Source code (.h/.cpp files)
│ ├── main.cpp # Main program entry point
│ ├── Circuit.h # Manages the overall circuit graph
│ ├── Node.h # Represents wires/connection points
│ ├── Gate.h # Base gate classes and specific implementations
│ └── TimingAnalyzer.h # Core STA algorithm engine
├── examples/ # Example circuit files
│ ├── simple_circuit.txt
│ ├── complex_circuit.txt
│ └── adder_circuit.txt
├── delays/ # Gate delay configuration files
│ └── gate_delays.txt
├── reports/ # Generated timing reports (created at runtime)
├── obj/ # Object files (created during build)
├── bin/ # Executable files (created during build)
└── README.md # This file
- A C++17 compatible compiler (e.g.,
g++orclang) make
-
Clone the repository:
git clone https://github.com/varnitsharma1085/DSA_Project_Static_Timing_Analysis.git cd Static-Timing-Analysis -
Build the executable: Run the build.bat file.
Simply run the sta.exe file created upon running build.bat file. In the "reports" folder the result will be saved of the example you have put in the main.cpp file in int main().
Alternatively When all the required files are in place, simply open main.cpp using vs code. Change the path of the circuit you want to analyze in the main function, execute the main.cpp file using any g++ compiler.
The entire analysis is a multi-step process orchestrated by the TimingAnalyzer.
-
Parsing & Graph Building:
- The
Circuitclass reads theexamples/anddelays/files. - It creates
Node(wire) andGateobjects. - It builds the graph by linking nodes to gates via
faninandfanoutpointers.
- The
-
Step 1: Forward Propagation (Arrival Time)
- A topological sort (Kahn's algorithm) is used to process nodes in the correct order (inputs first).
- The
arrivalTime(AT) is calculated for each node: - Formula:
AT_output = max(all_input_ATs) + gate_delay - This finds the longest time it takes for a signal to reach each node from the start.
-
Step 2: Backward Propagation (Required Time)
- A reverse topological sort is used, starting from the primary outputs.
- The
requiredTime(RT) is set to theCLOCK_PERIODfor all outputs. - The analyzer works backward, calculating the latest time a signal must arrive at a node to meet the clock deadline.
- Formula:
RT_input = min(all_output_RTs) - gate_delay
-
Step 3: Slack Calculation
- For every node in the graph, the slack (timing margin) is calculated.
- Formula:
Slack = RequiredTime - ArrivalTime Slack > 0: The signal arrived before it was needed (Good).Slack < 0: The signal arrived after it was needed (Timing Violation).
-
Step 4: Critical Path Finding
- A Depth-First Search (DFS) is used to find all possible paths from primary inputs to primary outputs.
- The critical path is the path with the lowest (most negative) slack. This is the slowest path in the circuit and determines its maximum operating speed.
The project is built on four key classes:
-
Node.h/cppRepresents a wire or connection point. This class is the "scorecard" that stores all timing data (arrivalTime,requiredTime,slack) and holds the graph structure (faninandfanoutpointers). -
Gate.h/cppUses inheritance and polymorphism to define a baseGateclass and all specific implementations (ANDGate,NOTGate, etc.). Each gate knows its own logic (evaluate()) and delay. AGateFactoryis used to create the correct gate object from a string (e.g., "AND"). -
Circuit.h/cppThe main "container" for the circuit. It holds amapof allNodeobjects (for fast lookup by name) and avectorof allGateobjects. It is responsible for parsing the input files and building the graph. -
TimingAnalyzer.h/cppThe "brain" of the operation. This class takes aCircuitobject and orchestrates all the key algorithms: the forward/backward traversals, slack calculation, path finding, and final report generation.
Defines the circuit structure using simple keywords:
# Comments start with a hash
CLOCK_PERIOD <time_in_ns>
INPUT <list_of_input_nodes>
OUTPUT <list_of_output_nodes>
GATE <gate_type> <gate_name> <output_node> <list_of_input_nodes>
# Example:
CLOCK_PERIOD 1.0
INPUT A B C
OUTPUT F
GATE AND G1 temp1 A B
GATE OR G2 F temp1 C
Defines the delay for each gate type.
# Comments start with a hash
<gate_type> <delay_in_ns>
# Example:
AND 0.1
OR 0.12
NOT 0.05
Adding a new logic gate is simple thanks to the object-oriented design:
-
Create the Gate Class:
- Create a new class (e.g.,
AND3Gate) inGate.h/cppthat inherits from the baseGateclass. - Implement its
evaluate()function for its specific logic.
- Create a new class (e.g.,
-
Add to the Factory:
- In
Gate.cpp, add your new gate to theGateFactory::createGatefunction:if (type == "AND3") return new AND3Gate(...);
- In
-
Add the Delay:
- Open
delays/gate_delays.txtand add the delay for your new gate:AND3 0.15
- Open
You can now use AND3 in your circuit files, and the analyzer will automatically support it.