Skip to content
Merged
Show file tree
Hide file tree
Changes from 29 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
211e65d
rmp: cut: Move logic cut/extractor to a new module
jbylicki Jun 4, 2025
cbb9e28
cgt: Clock gating
kbieganski Mar 28, 2025
b4e0d6a
cut: Only make MIO library once
kbieganski Jul 24, 2025
eb1ee9c
cgt: cut: Do not remove primary outputs
kbieganski Jul 23, 2025
8d521b3
cgt: Fix Python API
kbieganski Jul 25, 2025
89654a3
cgt: Add missing lib in CMakeLists
kbieganski Jul 25, 2025
4ff1cfd
cgt: Only init ABC once
kbieganski Jul 28, 2025
88bce45
cgt: Use `DebugScopedTimer` instead of a custom one
kbieganski Jul 28, 2025
0fb495e
cgt: Wrap ABC vectors in smart pointers
kbieganski Jul 28, 2025
bec7768
cgt: Error on multi-bit flip flops
kbieganski Jul 29, 2025
c8da7f3
cgt: rmp: Move `.abc_history` Git ignore to root
kbieganski Jul 29, 2025
16d0faa
cgt: Warn on unsupported clock gates
kbieganski Jul 29, 2025
70f5440
cgt: Disable layering check in Bazel
kbieganski Jul 30, 2025
654a5f2
cgt: Add missing test files to Bazel
kbieganski Jul 30, 2025
f304279
rmp: Add docs for `resynth`
kbieganski Jul 30, 2025
b778e55
utl: Fix formatting
kbieganski Jul 31, 2025
4ad95b9
Merge remote-tracking branch 'origin/master' into cgt
kbieganski Aug 14, 2025
9dfb10e
cgt: Fix iterator memory leaks
kbieganski Aug 15, 2025
361115b
cgt: Do not generate unique names for nets
kbieganski Aug 15, 2025
c9a6bbf
cgt: Use `utl::UniqueName`
kbieganski Aug 15, 2025
d642179
cgt: Fix and test Tcl params
kbieganski Aug 15, 2025
1a27887
cut: rmp: Link to sky130hd directory
kbieganski Aug 20, 2025
8de11b0
cgt: Remove dead code
kbieganski Aug 20, 2025
dc0cdb2
cgt: Check debug level fewer times
kbieganski Aug 20, 2025
2d2c940
Merge remote-tracking branch 'origin/master' into cgt
kbieganski Aug 21, 2025
449bc46
Merge remote-tracking branch 'origin/master' into cgt
kbieganski Aug 28, 2025
d67780e
cgt: Export more downstream nets
kbieganski Sep 4, 2025
884bde9
cgt: Check that gated nets are the same clocks
kbieganski Sep 4, 2025
481aef4
Merge remote-tracking branch 'origin/master' into cgt
kbieganski Sep 4, 2025
c7a8700
cgt: Error on gating distinct clocks
kbieganski Sep 4, 2025
9863b2c
cgt: Fix argument name
kbieganski Sep 4, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ TAGS
Makefile
__pycache__
venv/
.abc_history

include/ord/Version.hh

Expand Down
2 changes: 2 additions & 0 deletions BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,10 @@ OPENROAD_LIBRARY_DEPS = [
":ord",
"//src/ant",
"//src/ant:ui",
"//src/cgt",
"//src/cts",
"//src/cts:ui",
"//src/cut",
"//src/dbSta",
"//src/dbSta:ui",
"//src/dft",
Expand Down
2 changes: 2 additions & 0 deletions docs/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ entries:
title: Static Timing Analyzer (external)
- file: main/src/rsz/README
title: Gate Resizing
- file: main/src/cgt/README
title: Clock gating
- file: main/src/dpl/README
title: Detailed Placement
- file: main/src/cts/README
Expand Down
5 changes: 5 additions & 0 deletions include/ord/Design.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ namespace tap {
class Tapcell;
}

namespace cgt {
class ClockGating;
}

namespace cts {
class TritonCTS;
}
Expand Down Expand Up @@ -157,6 +161,7 @@ class Design

// Services
ant::AntennaChecker* getAntennaChecker();
cgt::ClockGating* getClockGating();
cts::TritonCTS* getTritonCts();
dft::Dft* getDft();
dpl::Opendp* getOpendp();
Expand Down
7 changes: 7 additions & 0 deletions include/ord/OpenRoad.hh
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ namespace ppl {
class IOPlacer;
}

namespace cgt {
class ClockGating;
}

namespace rmp {
class Restructure;
}
Expand Down Expand Up @@ -146,6 +150,7 @@ class OpenRoad
odb::dbDatabase* getDb() { return db_; }
sta::dbSta* getSta() { return sta_; }
sta::dbNetwork* getDbNetwork();
cgt::ClockGating* getClockGating() { return clock_gating_; }
rsz::Resizer* getResizer() { return resizer_; }
rmp::Restructure* getRestructure() { return restructure_; }
cts::TritonCTS* getTritonCts() { return tritonCts_; }
Expand Down Expand Up @@ -252,6 +257,7 @@ class OpenRoad
mpl::MacroPlacer* macro_placer_ = nullptr;
exa::Example* example_ = nullptr;
grt::GlobalRouter* global_router_ = nullptr;
cgt::ClockGating* clock_gating_ = nullptr;
rmp::Restructure* restructure_ = nullptr;
cts::TritonCTS* tritonCts_ = nullptr;
tap::Tapcell* tapcell_ = nullptr;
Expand All @@ -278,5 +284,6 @@ class OpenRoad

int tclAppInit(Tcl_Interp* interp);
int tclInit(Tcl_Interp* interp);
void abcInit();

} // namespace ord
5 changes: 5 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,9 @@ add_subdirectory(exa)
add_subdirectory(fin)
add_subdirectory(ppl)
add_subdirectory(rmp)
add_subdirectory(cgt)
add_subdirectory(cts)
add_subdirectory(cut)
add_subdirectory(grt)
add_subdirectory(tap)
add_subdirectory(rcx)
Expand Down Expand Up @@ -328,7 +330,9 @@ target_link_libraries(openroad
odbtcl
rcx
rmp
cgt
cts
cut
grt
tap
gui
Expand Down Expand Up @@ -409,6 +413,7 @@ if (Python3_FOUND AND BUILD_PYTHON)
exa_py
ppl_py
tap_py
cgt_py
cts_py
drt_py
fin_py
Expand Down
5 changes: 5 additions & 0 deletions src/Design.cc
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,11 @@ tap::Tapcell* Design::getTapcell()
return getOpenRoad()->getTapcell();
}

cgt::ClockGating* Design::getClockGating()
{
return getOpenRoad()->getClockGating();
}

cts::TritonCTS* Design::getTritonCts()
{
return getOpenRoad()->getTritonCts();
Expand Down
20 changes: 20 additions & 0 deletions src/Main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ using std::string;
X(par) \
X(rcx) \
X(rmp) \
X(cgt) \
X(stt) \
X(psm) \
X(pdn) \
Expand All @@ -88,6 +89,7 @@ static const char* log_filename = nullptr;
static const char* metrics_filename = nullptr;
static bool no_settings = false;
static bool minimize = false;
static bool abc_initialized = false;

static const char* init_filename = ".openroad";

Expand Down Expand Up @@ -167,6 +169,12 @@ static void initPython()
}
#endif

namespace abc {
// Forward declare instead of including to avoid warnings from ABC
void Abc_Start();
void Abc_Stop();
} // namespace abc

static volatile sig_atomic_t fatal_error_in_progress = 0;

// When we enter through main() we have a single tech and design.
Expand Down Expand Up @@ -301,6 +309,10 @@ int main(int argc, char* argv[])
// Set argc to 1 so Tcl_Main doesn't source any files.
// Tcl_Main never returns.
Tcl_Main(1, argv, ord::tclAppInit);

if (abc_initialized) {
abc::Abc_Stop();
}
return 0;
}

Expand Down Expand Up @@ -516,6 +528,14 @@ int ord::tclInit(Tcl_Interp* interp)
return tclAppInit(cmd_argc, cmd_argv, init_filename, interp);
}

void ord::abcInit()
{
if (!abc_initialized) {
abc::Abc_Start();
abc_initialized = true;
}
}

static void showUsage(const char* prog, const char* init_filename)
{
printf("Usage: %s [-help] [-version] [-no_init] [-no_splash] [-exit] ", prog);
Expand Down
3 changes: 3 additions & 0 deletions src/OpenRoad.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#endif

#include "ant/MakeAntennaChecker.hh"
#include "cgt/MakeClockGating.h"
#include "cts/MakeTritoncts.h"
#include "db_sta/MakeDbSta.hh"
#include "db_sta/dbNetwork.hh"
Expand Down Expand Up @@ -179,6 +180,7 @@ void OpenRoad::init(Tcl_Interp* tcl_interp,
finale_ = fin::makeFinale();
global_router_ = grt::makeGlobalRouter();
restructure_ = rmp::makeRestructure();
clock_gating_ = cgt::makeClockGating();
tritonCts_ = cts::makeTritonCts();
tapcell_ = tap::makeTapcell();
macro_placer_ = mpl::makeMacroPlacer();
Expand Down Expand Up @@ -259,6 +261,7 @@ void OpenRoad::init(Tcl_Interp* tcl_interp,
resizer_,
estimate_parasitics_,
tcl_interp);
cgt::initClockGating(clock_gating_, tcl_interp, logger_, sta_);
initTritonRoute(detailed_router_,
db_,
logger_,
Expand Down
7 changes: 7 additions & 0 deletions src/OpenRoad.i
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,13 @@ getResizer()
return openroad->getResizer();
}

cgt::ClockGating *
getClockGating()
{
OpenRoad *openroad = getOpenRoad();
return openroad->getClockGating();
}

est::EstimateParasitics *
getEstimateParasitics()
{
Expand Down
1 change: 1 addition & 0 deletions src/cgt/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
test/results
63 changes: 63 additions & 0 deletions src/cgt/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# SPDX-License-Identifier: BSD-3-Clause
# Copyright (c) 2025, The OpenROAD Authors

load("//bazel:tcl_encode_or.bzl", "tcl_encode")
load("//bazel:tcl_wrap_cc.bzl", "tcl_wrap_cc")

package(
default_visibility = ["//:__subpackages__"],
# ABC headers have duplicate declarations which cause warnings/compile errors.
# This was solved by including more specific individual headers, but those are private, so the layering check is disabled.
# features = ["layering_check"],
)

cc_library(
name = "cgt",
srcs = [
"src/ClockGating.cpp",
"src/MakeClockGating.cpp",
"src/NetworkBuilder.cpp",
":swig",
":tcl",
],
hdrs = [
"include/cgt/ClockGating.h",
"include/cgt/MakeClockGating.h",
"include/cgt/NetworkBuilder.h",
"include/cgt/RandomBits.h",
],
includes = [
"include",
],
deps = [
"//:ord",
"//src/odb",
"//src/dbSta",
"//src/sta:opensta_lib",
"//src/cut",
"//src/utl",
"@boost.stacktrace",
"@edu_berkeley_abc//:abc-lib",
"@tk_tcl//:tcl",
],
)

tcl_encode(
name = "tcl",
srcs = [
"src/cgt.tcl",
],
char_array_name = "cgt_tcl_inits",
namespace = "cgt",
)

tcl_wrap_cc(
name = "swig",
srcs = [
"src/cgt.i",
"//:error_swig",
],
module = "cgt",
namespace_prefix = "cgt",
root_swig_src = "src/cgt.i",
)
8 changes: 8 additions & 0 deletions src/cgt/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
## SPDX-License-Identifier: BSD-3-Clause
## Copyright (c) 2025, The OpenROAD Authors

add_subdirectory(src)

if (ENABLE_TESTS)
add_subdirectory(test)
endif()
90 changes: 90 additions & 0 deletions src/cgt/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# Clock gating

This module provides automatic insertion of clock gates for reducing power usage.
It uses ABC for proving correctness of gating conditions.

The process is roughly:
1. For each register:
a. Gather nets connected to the register via BFS (limited to 100 nets for performance, user configurable).
If it encounters a register, it doesn't go through it; it stops there and goes in different directions.
b. Check if a previously accepted gating condition can be reused; if so, add this register to that condition's list of registers.
c. Export the network gathered in (a) to ABC.
d. Check if all the nets in the exported network can form a correct gating condition using ABC.
- First, simulation with random stimuli quickly looks for counterexamples.
- Then, if no counterexample was found, a SAT solver is employed to prove that the gating condition is correct.
A clock enable condition is checked by ORing the nets, and a clock disable condition by ANDing them.
e. If the set of all nets doesn't form a correct gating condition, move on to the next register.
Otherwise:
- Check if after removing half of the nets the gating condition still works.
- If so, drop the other half of the nets. Otherwise, recurse into the other half of the nets to minimize that subset.
- Then, recurse into the first half of the nets to minimize that part.
This produces a minimal set of nets that form a gating condition (not necessarily optimal).
f. Add the minimal set of nets with the corresponding gated register to a list of accepted gating conditions.
First check if it doesn't contain it already; if it does, add the gated register to the pre-existing condition's list of registers.
2. For each accepted gating condition with at least 10 corresponding registers (user-configurable),
insert a new clock gate that gates the corresponding registers under this condition.

Usage:

```tcl
read_liberty path/to/pdk/cell/library.lib
read_db path/to/your/design.odb
read_sdc path/to/your/constraints.sdc

clock_gating
```

## Commands

```{note}
All parameters for clock gating are optional, as indicated by square brackets: `[-param param]`.
```

### Clock gating

```tcl
clock_gating
[-min_instances min_instances]
[-max_cover max_cover]
[-dump_dir dump_dir]
```

#### Options

| Switch Name | Description |
| ----- | ----- |
| `-min_instances` | Minimum number of instances that should be gated by a single clock gate. |
| `-max_cover` | Maximum number of initial gate condition candidate nets per instance. |
| `-dump_dir` | Directory for debug dumps. |

## Example scripts

Example script on running `cgt` for a sample design of `aes` can be found here:

```
./test/aes_nangate45.tcl
```

## Regression tests

There are a set of regression tests in `./test`. For more information, refer to this [section](../../README.md#regression-tests).

Simply run the following script:

```shell
./test/regression
```

## Limitations

Clock gating is currently not available for designs that contain HA and FA cells which are not supported by ABC.

## FAQs

Check out [GitHub discussion](https://github.com/The-OpenROAD-Project/OpenROAD/discussions/categories/q-a?discussions_q=category%3AQ%26A+clock-gating)
about this tool.

## References

1. Aaron P. Hurst. 2008. Automatic synthesis of clock gating logic with controlled netlist perturbation. In Proceedings of the 45th annual Design Automation Conference (DAC '08). Association for Computing Machinery, New York, NY, USA, 654–657. https://doi.org/10.1145/1391469.1391637

Loading
Loading