Merge pull request #370 from The-OpenROAD-Project-staging/sta_latest_0609
Sta latest 0609
This commit is contained in:
commit
244797f162
|
|
@ -1,15 +1,22 @@
|
||||||
---
|
---
|
||||||
description: C++ coding standards and formatting for OpenSTA
|
description: C++ coding standards and formatting for OpenSTA
|
||||||
globs: ["**/*.cc", "**/*.hh", "**/*.h"]
|
globs: ["**/*.cc", "**/*.hh", "**/*.h"]
|
||||||
alwaysApply: false
|
alwaysApply: true
|
||||||
---
|
---
|
||||||
|
|
||||||
# C++ Coding Standards
|
# C++ Coding Standards
|
||||||
|
|
||||||
|
## File-internal helpers (translation-unit local)
|
||||||
|
|
||||||
|
- For helpers used only in one `.cc` file, put them in the **same namespace** as the rest of the implementation (e.g. `namespace sta { ... }`).
|
||||||
|
- Mark them **`static`** at namespace scope so they have internal linkage.
|
||||||
|
- **Do not** wrap them in an **anonymous namespace** in this project (no `namespace { ... }` file-static helpers). The user preference is `static` inside the real namespace, not a nested anonymous namespace inside `sta` or at file scope before `sta`.
|
||||||
|
|
||||||
## Line Width
|
## Line Width
|
||||||
|
|
||||||
- **Keep lines under 90 characters** to match `.clang-format` (ColumnLimit: 90).
|
- **Keep lines under 90 characters** to match `.clang-format` (ColumnLimit: 90).
|
||||||
- Break long lines at logical points: after commas, before operators, after opening parens.
|
- Only break a line when it would exceed 90 characters. Do not introduce unnecessary line breaks when the expression fits on one line.
|
||||||
|
- When a break is needed, break at logical points: after commas, before operators. Keep the first argument on the same line as the opening paren (do not break immediately after an opening paren).
|
||||||
|
|
||||||
## Naming Conventions
|
## Naming Conventions
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
FROM ubuntu:24.04
|
||||||
|
LABEL author="James Cherry"
|
||||||
|
LABEL maintainer="James Cherry <cherry@parallaxsw.com>"
|
||||||
|
|
||||||
|
# Install basics
|
||||||
|
ARG DEBIAN_FRONTEND=noninteractive
|
||||||
|
RUN apt-get update && \
|
||||||
|
apt-get install -y \
|
||||||
|
git \
|
||||||
|
wget \
|
||||||
|
cmake \
|
||||||
|
gcc \
|
||||||
|
gdb \
|
||||||
|
tcl-dev \
|
||||||
|
tcl-tclreadline \
|
||||||
|
swig \
|
||||||
|
bison \
|
||||||
|
flex \
|
||||||
|
automake \
|
||||||
|
autotools-dev \
|
||||||
|
libeigen3-dev \
|
||||||
|
libfmt-dev
|
||||||
|
|
||||||
|
# Download CUDD
|
||||||
|
RUN wget https://raw.githubusercontent.com/davidkebo/cudd/main/cudd_versions/cudd-3.0.0.tar.gz && \
|
||||||
|
tar -xvf cudd-3.0.0.tar.gz && \
|
||||||
|
rm cudd-3.0.0.tar.gz
|
||||||
|
|
||||||
|
# Build CUDD
|
||||||
|
RUN cd cudd-3.0.0 && \
|
||||||
|
mkdir ../cudd && \
|
||||||
|
./configure && \
|
||||||
|
make -j`nproc`
|
||||||
|
|
||||||
|
# Copy files and install OpenSTA
|
||||||
|
RUN mkdir OpenSTA
|
||||||
|
COPY . OpenSTA
|
||||||
|
RUN cd OpenSTA && \
|
||||||
|
rm -rf build && \
|
||||||
|
mkdir build && \
|
||||||
|
cd build && \
|
||||||
|
cmake -DCUDD_DIR=../cudd-3.0.0 .. && \
|
||||||
|
make -j`nproc`
|
||||||
|
|
||||||
|
# Run sta on entry
|
||||||
|
ENTRYPOINT ["OpenSTA/build/sta"]
|
||||||
|
|
@ -194,7 +194,7 @@ following command builds a Docker image.
|
||||||
|
|
||||||
```
|
```
|
||||||
cd OpenSTA
|
cd OpenSTA
|
||||||
docker build --file Dockerfile.ubuntu22.04 --tag opensta_ubuntu22.04 .
|
docker build --file Dockerfile.ubuntu24.04 --tag opensta_ubuntu24.04 .
|
||||||
or
|
or
|
||||||
docker build --file Dockerfile.centos7 --tag opensta_centos7 .
|
docker build --file Dockerfile.centos7 --tag opensta_centos7 .
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -29,14 +29,14 @@ set(TCL_POSSIBLE_NAMES
|
||||||
tcl85 tcl8.5
|
tcl85 tcl8.5
|
||||||
)
|
)
|
||||||
|
|
||||||
# tcl lib path guesses.
|
# TCL lib path guesses.
|
||||||
if (NOT TCL_LIB_PATHS)
|
if (NOT TCL_LIB_PATHS)
|
||||||
if (CMAKE_SYSTEM_NAME STREQUAL "Darwin")
|
if (CMAKE_SYSTEM_NAME STREQUAL "Darwin")
|
||||||
|
file(GLOB tcl_homebrew_libs
|
||||||
|
/opt/homebrew/Cellar/tcl-tk@8/*/lib
|
||||||
|
)
|
||||||
set(TCL_LIB_PATHS
|
set(TCL_LIB_PATHS
|
||||||
#/opt/homebrew/Cellar/tcl-tk/9.0.3/lib
|
${tcl_homebrew_libs}
|
||||||
/opt/homebrew/Cellar/tcl-tk@8/8.6.18/lib
|
|
||||||
/opt/homebrew/Cellar/tcl-tk@8/8.6.17/lib
|
|
||||||
/opt/homebrew/Cellar/tcl-tk@8/8.6.16/lib
|
|
||||||
/opt/homebrew/opt/tcl-tk/lib /usr/local/lib)
|
/opt/homebrew/opt/tcl-tk/lib /usr/local/lib)
|
||||||
set(TCL_NO_DEFAULT_PATH TRUE)
|
set(TCL_NO_DEFAULT_PATH TRUE)
|
||||||
elseif (CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
elseif (CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||||
|
|
|
||||||
|
|
@ -22,13 +22,13 @@ Release 3.0.1 2026/03/12
|
||||||
------------------------
|
------------------------
|
||||||
|
|
||||||
Statistical timing (SSTA) with Liberty LVF (Liberty Variation Format)
|
Statistical timing (SSTA) with Liberty LVF (Liberty Variation Format)
|
||||||
models is now supported. Statistical timing uses a probaility
|
models is now supported. Statistical timing uses a probability
|
||||||
distribution to represent a delay or slew ranther than a single
|
distribution to represent a delay or slew rather than a single
|
||||||
number.
|
number.
|
||||||
|
|
||||||
Normal and skew normal probability distributions are supported.
|
Normal and skew normal probability distributions are supported.
|
||||||
|
|
||||||
SSTA is enabled with the sta_pocv_mode variaable.
|
SSTA is enabled with the sta_pocv_mode variable.
|
||||||
|
|
||||||
set sta_pocv_mode scalar|normal|skew_normal
|
set sta_pocv_mode scalar|normal|skew_normal
|
||||||
|
|
||||||
|
|
@ -43,10 +43,10 @@ set with the sta_pocv_quantile variable.
|
||||||
|
|
||||||
The default value is 3 standard deviations, or sigma.
|
The default value is 3 standard deviations, or sigma.
|
||||||
|
|
||||||
Use the variance field with report_checks or report_check_types to see
|
Use the variation field with report_checks or report_check_types to see
|
||||||
distribution parameters in timing reports.
|
distribution parameters in timing reports.
|
||||||
|
|
||||||
A command file for analyzing a design with statisical timing with an
|
A command file for analyzing a design with statistical timing with an
|
||||||
LVF library is shown below.
|
LVF library is shown below.
|
||||||
|
|
||||||
read_liberty lvf_library.lib.gz
|
read_liberty lvf_library.lib.gz
|
||||||
|
|
|
||||||
|
|
@ -6639,15 +6639,15 @@
|
||||||
<text:p text:style-name="P17">This example can be found in <text:span text:style-name="T8">examples/</text:span><text:span text:style-name="T10">mcmm3</text:span><text:span text:style-name="T8">.tcl</text:span>.<text:line-break/><text:line-break/><text:span text:style-name="T6">In the example show above the SDC for the modes is in separate files. Alternatively, the SDC can be defined in the command file using the </text:span><text:span text:style-name="T13">set_mode</text:span><text:span text:style-name="T6"> command between SDC command groups.</text:span></text:p>
|
<text:p text:style-name="P17">This example can be found in <text:span text:style-name="T8">examples/</text:span><text:span text:style-name="T10">mcmm3</text:span><text:span text:style-name="T8">.tcl</text:span>.<text:line-break/><text:line-break/><text:span text:style-name="T6">In the example show above the SDC for the modes is in separate files. Alternatively, the SDC can be defined in the command file using the </text:span><text:span text:style-name="T13">set_mode</text:span><text:span text:style-name="T6"> command between SDC command groups.</text:span></text:p>
|
||||||
<text:p text:style-name="P18"><text:span text:style-name="T6">set_mode mode1<text:line-break/>create_clock -name m1_clk -period 1000 {clk1 clk2 clk3}<text:line-break/></text:span>set_input_delay -clock m1_clk 100 {in1 in2}<text:line-break/><text:line-break/><text:span text:style-name="T6">set_mode mode2<text:line-break/>create_clock -name m2_clk -period 500 {clk1 clk3}<text:line-break/></text:span>set_output_delay -clock m2_clk 100 out</text:p>
|
<text:p text:style-name="P18"><text:span text:style-name="T6">set_mode mode1<text:line-break/>create_clock -name m1_clk -period 1000 {clk1 clk2 clk3}<text:line-break/></text:span>set_input_delay -clock m1_clk 100 {in1 in2}<text:line-break/><text:line-break/><text:span text:style-name="T6">set_mode mode2<text:line-break/>create_clock -name m2_clk -period 500 {clk1 clk3}<text:line-break/></text:span>set_output_delay -clock m2_clk 100 out</text:p>
|
||||||
<text:h text:style-name="P19" text:outline-level="2"><text:bookmark-start text:name="__RefHeading___Toc42583_2528141652 Copy 1"/>Statistical Timing Analysis<text:bookmark-end text:name="__RefHeading___Toc42583_2528141652 Copy 1"/></text:h>
|
<text:h text:style-name="P19" text:outline-level="2"><text:bookmark-start text:name="__RefHeading___Toc42583_2528141652 Copy 1"/>Statistical Timing Analysis<text:bookmark-end text:name="__RefHeading___Toc42583_2528141652 Copy 1"/></text:h>
|
||||||
<text:p text:style-name="Body_20_first">OpenSTA also supports <text:span text:style-name="T14">statistical timing </text:span>.<text:span text:style-name="T14">anallysis with Liberty Variation Format (LVF) libraries. Statistical timing uses a probaility </text:span>distribution to represent a delay or slew ranther than a single number.</text:p>
|
<text:p text:style-name="Body_20_first">OpenSTA also supports <text:span text:style-name="T14">statistical timing </text:span><text:span text:style-name="T14">analysis with Liberty Variation Format (LVF) libraries. Statistical timing uses a probability </text:span>distribution to represent a delay or slew rather than a single number.</text:p>
|
||||||
<text:p text:style-name="P20"><text:soft-page-break/>Normal and skew normal probability distributions are supported. <text:s/>SSTA is enabled with the <text:span text:style-name="T12">sta_pocv_mode</text:span> variaable.</text:p>
|
<text:p text:style-name="P20"><text:soft-page-break/>Normal and skew normal probability distributions are supported. <text:s/>SSTA is enabled with the <text:span text:style-name="T12">sta_pocv_mode</text:span> variable.</text:p>
|
||||||
<text:p text:style-name="Example_20__20_indented">set sta_pocv_mode scalar|normal|skew_normal<text:line-break/><text:line-break/><text:span text:style-name="T15">scalar mode is for non-SSTA analysis<text:line-break/>normal mode uses gaussian normal distributions<text:line-break/>skew_normal mode is for skew normal LVF moment based distributions</text:span></text:p>
|
<text:p text:style-name="Example_20__20_indented">set sta_pocv_mode scalar|normal|skew_normal<text:line-break/><text:line-break/><text:span text:style-name="T15">scalar mode is for non-SSTA analysis<text:line-break/>normal mode uses gaussian normal distributions<text:line-break/>skew_normal mode is for skew normal LVF moment based distributions</text:span></text:p>
|
||||||
<text:p text:style-name="P20">The target quantile of a delay probability distribution (confidence level) is set with the <text:span text:style-name="T12">sta_pocv_quantile</text:span> variable.</text:p>
|
<text:p text:style-name="P20">The target quantile of a delay probability distribution (confidence level) is set with the <text:span text:style-name="T12">sta_pocv_quantile</text:span> variable.</text:p>
|
||||||
<text:p text:style-name="Example_20__20_indented"><text:span text:style-name="T16">set </text:span>sta_pocv_quantile <float></text:p>
|
<text:p text:style-name="Example_20__20_indented"><text:span text:style-name="T16">set </text:span>sta_pocv_quantile <float></text:p>
|
||||||
<text:p text:style-name="P20">The default value is 3 standard deviations, or sigma.</text:p>
|
<text:p text:style-name="P20">The default value is 3 standard deviations, or sigma.</text:p>
|
||||||
<text:p text:style-name="P21"><text:span text:style-name="T16">Use the </text:span><text:span text:style-name="T12">variance</text:span> <text:span text:style-name="T16">field with the </text:span>report_checks <text:span text:style-name="T16">and</text:span> report_check_types <text:span text:style-name="T16">commands to see distribution parameters in timing reports.</text:span></text:p>
|
<text:p text:style-name="P21"><text:span text:style-name="T16">Use the </text:span><text:span text:style-name="T12">variation</text:span> <text:span text:style-name="T16">field with the </text:span>report_checks <text:span text:style-name="T16">and</text:span> report_check_types <text:span text:style-name="T16">commands to see distribution parameters in timing reports.</text:span></text:p>
|
||||||
<text:p text:style-name="P22">A command file for analyzing a design with statisical timing is shown below.</text:p>
|
<text:p text:style-name="P22">A command file for analyzing a design with statistical timing is shown below.</text:p>
|
||||||
<text:p text:style-name="Example_20__20_indented"><text:soft-page-break/>read_liberty lvf_library.lib.gz<text:line-break/>read_verilog design.v<text:line-break/>link_design topcreate_clock -period 50 clk<text:line-break/>set_input_delay -clock clk 1 {in1 in2}<text:line-break/>set sta_pocv_mode skew_normal<text:line-break/>report_checks -fields {slew variation input_pin variation} -digits 3</text:p>
|
<text:p text:style-name="Example_20__20_indented"><text:soft-page-break/>read_liberty lvf_library.lib.gz<text:line-break/>read_verilog design.v<text:line-break/>link_design topcreate_clock -period 50 clk<text:line-break/>set_input_delay -clock clk 1 {in1 in2}<text:line-break/>set sta_pocv_mode skew_normal<text:line-break/>report_checks -fields {slew variation input_pin} -digits 3</text:p>
|
||||||
<text:p text:style-name="Example_20__20_indented"><text:soft-page-break/><text:span text:style-name="T16">Startpoint: r2 (rising edge-triggered flip-flop clocked by clk)<text:line-break/>Endpoint: r3 (rising edge-triggered flip-flop clocked by clk)<text:line-break/>Path Group: clk<text:line-break/>Path Type: max<text:line-break/><text:line-break/> <text:s text:c="3"/>Slew <text:s text:c="3"/>Delay Variation <text:s text:c="4"/>Time <text:s text:c="2"/>Description<text:line-break/>---------------------------------------------------------------------------<text:line-break/> <text:s text:c="2"/>0.000 <text:s text:c="3"/>0.000 <text:s text:c="12"/>0.000 <text:s text:c="2"/>clock clk (rise edge)<text:line-break/> <text:s text:c="11"/>0.000 <text:s text:c="12"/>0.000 <text:s text:c="2"/>clock network delay (ideal)<text:line-break/> <text:s text:c="2"/>0.000 <text:s text:c="3"/>0.000 <text:s text:c="12"/>0.000 ^ r2/CK (FDPQ1)<text:line-break/> <text:s text:c="19"/>12.026 <text:s text:c="11"/>mean<text:line-break/> <text:s text:c="20"/>0.017 <text:s text:c="11"/>mean_shift<text:line-break/> <text:s text:c="20"/>0.366 <text:s text:c="11"/>std_dev<text:line-break/> <text:s text:c="20"/>0.000 <text:s text:c="11"/>skewness<text:line-break/> <text:s text:c="2"/>4.648 <text:s text:c="2"/>12.409 <text:s text:c="11"/>12.409 v r2/Q (FFQ1)<text:line-break/> <text:s text:c="2"/>4.648 <text:s text:c="3"/>0.000 <text:s text:c="11"/>12.409 v u1/A (BUF1)<text:line-break/> <text:s text:c="20"/>6.084 <text:s text:c="11"/>mean<text:line-break/> <text:s text:c="20"/>0.007 <text:s text:c="11"/>mean_shift<text:line-break/> <text:s text:c="20"/>0.188 <text:s text:c="11"/>std_dev<text:line-break/> <text:s text:c="20"/>0.000 <text:s text:c="11"/>skewness<text:line-break/> <text:s text:c="2"/>2.513 <text:s text:c="3"/>6.137 <text:s text:c="11"/>18.546 v u1/X (BUF1)<text:line-break/> <text:s text:c="2"/>2.513 <text:s text:c="3"/>0.000 <text:s text:c="11"/>18.546 v u2/A2 (AN21)<text:line-break/> <text:s text:c="20"/>6.447 <text:s text:c="11"/>mean<text:line-break/> <text:s text:c="20"/>0.008 <text:s text:c="11"/>mean_shift<text:line-break/> <text:s text:c="20"/>0.191 <text:s text:c="11"/>std_dev<text:line-break/> <text:s text:c="20"/>0.000 <text:s text:c="11"/>skewness<text:line-break/> <text:s text:c="2"/>2.565 <text:s text:c="3"/>6.497 <text:s text:c="11"/>25.043 v u2/X (AN21)<text:line-break/> <text:s text:c="2"/>2.565 <text:s text:c="3"/>0.000 <text:s text:c="11"/>25.043 v r3/D (FFQ1)<text:line-break/> <text:s text:c="28"/>25.043 <text:s text:c="2"/>data arrival time<text:line-break/></text:span><text:line-break/> <text:s text:c="2"/>0.000 <text:s text:c="2"/>50.000 <text:s text:c="11"/>50.000 <text:s text:c="2"/>clock clk (rise edge)<text:line-break/> <text:s text:c="11"/>0.000 <text:s text:c="11"/>50.000 <text:s text:c="2"/>clock network delay (ideal)<text:line-break/> <text:s text:c="11"/>0.000 <text:s text:c="11"/>50.000 <text:s text:c="2"/>clock reconvergence pessimism<text:line-break/> <text:s text:c="28"/>50.000 ^ r3/CK (FFQ1)<text:line-break/> <text:s text:c="10"/>-9.376 <text:s text:c="11"/>40.624 <text:s text:c="2"/>library setup time<text:line-break/> <text:s text:c="28"/>40.624 <text:s text:c="2"/>data required time<text:line-break/>---------------------------------------------------------------------------<text:line-break/> <text:s text:c="28"/>40.624 <text:s text:c="2"/>data required time<text:line-break/> <text:s text:c="27"/>-25.043 <text:s text:c="2"/>data arrival time<text:line-break/>---------------------------------------------------------------------------<text:line-break/> <text:s text:c="28"/>15.581 <text:s text:c="2"/>slack (MET)</text:p>
|
<text:p text:style-name="Example_20__20_indented"><text:soft-page-break/><text:span text:style-name="T16">Startpoint: r2 (rising edge-triggered flip-flop clocked by clk)<text:line-break/>Endpoint: r3 (rising edge-triggered flip-flop clocked by clk)<text:line-break/>Path Group: clk<text:line-break/>Path Type: max<text:line-break/><text:line-break/> <text:s text:c="3"/>Slew <text:s text:c="3"/>Delay Variation <text:s text:c="4"/>Time <text:s text:c="2"/>Description<text:line-break/>---------------------------------------------------------------------------<text:line-break/> <text:s text:c="2"/>0.000 <text:s text:c="3"/>0.000 <text:s text:c="12"/>0.000 <text:s text:c="2"/>clock clk (rise edge)<text:line-break/> <text:s text:c="11"/>0.000 <text:s text:c="12"/>0.000 <text:s text:c="2"/>clock network delay (ideal)<text:line-break/> <text:s text:c="2"/>0.000 <text:s text:c="3"/>0.000 <text:s text:c="12"/>0.000 ^ r2/CK (FDPQ1)<text:line-break/> <text:s text:c="19"/>12.026 <text:s text:c="11"/>mean<text:line-break/> <text:s text:c="20"/>0.017 <text:s text:c="11"/>mean_shift<text:line-break/> <text:s text:c="20"/>0.366 <text:s text:c="11"/>std_dev<text:line-break/> <text:s text:c="20"/>0.000 <text:s text:c="11"/>skewness<text:line-break/> <text:s text:c="2"/>4.648 <text:s text:c="2"/>12.409 <text:s text:c="11"/>12.409 v r2/Q (FFQ1)<text:line-break/> <text:s text:c="2"/>4.648 <text:s text:c="3"/>0.000 <text:s text:c="11"/>12.409 v u1/A (BUF1)<text:line-break/> <text:s text:c="20"/>6.084 <text:s text:c="11"/>mean<text:line-break/> <text:s text:c="20"/>0.007 <text:s text:c="11"/>mean_shift<text:line-break/> <text:s text:c="20"/>0.188 <text:s text:c="11"/>std_dev<text:line-break/> <text:s text:c="20"/>0.000 <text:s text:c="11"/>skewness<text:line-break/> <text:s text:c="2"/>2.513 <text:s text:c="3"/>6.137 <text:s text:c="11"/>18.546 v u1/X (BUF1)<text:line-break/> <text:s text:c="2"/>2.513 <text:s text:c="3"/>0.000 <text:s text:c="11"/>18.546 v u2/A2 (AN21)<text:line-break/> <text:s text:c="20"/>6.447 <text:s text:c="11"/>mean<text:line-break/> <text:s text:c="20"/>0.008 <text:s text:c="11"/>mean_shift<text:line-break/> <text:s text:c="20"/>0.191 <text:s text:c="11"/>std_dev<text:line-break/> <text:s text:c="20"/>0.000 <text:s text:c="11"/>skewness<text:line-break/> <text:s text:c="2"/>2.565 <text:s text:c="3"/>6.497 <text:s text:c="11"/>25.043 v u2/X (AN21)<text:line-break/> <text:s text:c="2"/>2.565 <text:s text:c="3"/>0.000 <text:s text:c="11"/>25.043 v r3/D (FFQ1)<text:line-break/> <text:s text:c="28"/>25.043 <text:s text:c="2"/>data arrival time<text:line-break/></text:span><text:line-break/> <text:s text:c="2"/>0.000 <text:s text:c="2"/>50.000 <text:s text:c="11"/>50.000 <text:s text:c="2"/>clock clk (rise edge)<text:line-break/> <text:s text:c="11"/>0.000 <text:s text:c="11"/>50.000 <text:s text:c="2"/>clock network delay (ideal)<text:line-break/> <text:s text:c="11"/>0.000 <text:s text:c="11"/>50.000 <text:s text:c="2"/>clock reconvergence pessimism<text:line-break/> <text:s text:c="28"/>50.000 ^ r3/CK (FFQ1)<text:line-break/> <text:s text:c="10"/>-9.376 <text:s text:c="11"/>40.624 <text:s text:c="2"/>library setup time<text:line-break/> <text:s text:c="28"/>40.624 <text:s text:c="2"/>data required time<text:line-break/>---------------------------------------------------------------------------<text:line-break/> <text:s text:c="28"/>40.624 <text:s text:c="2"/>data required time<text:line-break/> <text:s text:c="27"/>-25.043 <text:s text:c="2"/>data arrival time<text:line-break/>---------------------------------------------------------------------------<text:line-break/> <text:s text:c="28"/>15.581 <text:s text:c="2"/>slack (MET)</text:p>
|
||||||
<text:p text:style-name="P23">The standard deviation for <text:span text:style-name="T14">n</text:span>ormal distributions is specified with the following liberty timing groups.</text:p>
|
<text:p text:style-name="P23">The standard deviation for <text:span text:style-name="T14">n</text:span>ormal distributions is specified with the following liberty timing groups.</text:p>
|
||||||
<text:p text:style-name="P24"><text:soft-page-break/>ocv_sigma_cell_rise<text:line-break/>ocv_sigma_cell_fall<text:line-break/>ocv_sigma_rise_transition<text:line-break/>ocv_sigma_fall_transition<text:line-break/>ocv_sigma_rise_constraint<text:line-break/>ocv_sigma_fall_constraint</text:p>
|
<text:p text:style-name="P24"><text:soft-page-break/>ocv_sigma_cell_rise<text:line-break/>ocv_sigma_cell_fall<text:line-break/>ocv_sigma_rise_transition<text:line-break/>ocv_sigma_fall_transition<text:line-break/>ocv_sigma_rise_constraint<text:line-break/>ocv_sigma_fall_constraint</text:p>
|
||||||
|
|
@ -9532,7 +9532,7 @@
|
||||||
<text:p text:style-name="P160">fields</text:p>
|
<text:p text:style-name="P160">fields</text:p>
|
||||||
</table:table-cell>
|
</table:table-cell>
|
||||||
<table:table-cell table:style-name="Table52.A2" office:value-type="string">
|
<table:table-cell table:style-name="Table52.A2" office:value-type="string">
|
||||||
<text:p text:style-name="P151"><text:span text:style-name="Default_20_Paragraph_20_Font">List of </text:span><text:span text:style-name="Default_20_Paragraph_20_Font"><text:span text:style-name="T12">capacitance|slew|input_pins|</text:span></text:span><text:span text:style-name="Default_20_Paragraph_20_Font"><text:span text:style-name="T173">hierarc</text:span></text:span><text:span text:style-name="Default_20_Paragraph_20_Font"><text:span text:style-name="T174">h</text:span></text:span><text:span text:style-name="Default_20_Paragraph_20_Font"><text:span text:style-name="T173">i</text:span></text:span><text:span text:style-name="Default_20_Paragraph_20_Font"><text:span text:style-name="T174">c</text:span></text:span><text:span text:style-name="Default_20_Paragraph_20_Font"><text:span text:style-name="T173">al_pins|</text:span></text:span><text:span text:style-name="Default_20_Paragraph_20_Font"><text:span text:style-name="T12">nets|fanout</text:span></text:span><text:span text:style-name="Default_20_Paragraph_20_Font"><text:span text:style-name="T175">|src_attr</text:span></text:span><text:span text:style-name="Default_20_Paragraph_20_Font"><text:span text:style-name="T176">|variance</text:span></text:span></text:p>
|
<text:p text:style-name="P151"><text:span text:style-name="Default_20_Paragraph_20_Font">List of </text:span><text:span text:style-name="Default_20_Paragraph_20_Font"><text:span text:style-name="T12">capacitance|slew|input_pins|</text:span></text:span><text:span text:style-name="Default_20_Paragraph_20_Font"><text:span text:style-name="T173">hierarc</text:span></text:span><text:span text:style-name="Default_20_Paragraph_20_Font"><text:span text:style-name="T174">h</text:span></text:span><text:span text:style-name="Default_20_Paragraph_20_Font"><text:span text:style-name="T173">i</text:span></text:span><text:span text:style-name="Default_20_Paragraph_20_Font"><text:span text:style-name="T174">c</text:span></text:span><text:span text:style-name="Default_20_Paragraph_20_Font"><text:span text:style-name="T173">al_pins|</text:span></text:span><text:span text:style-name="Default_20_Paragraph_20_Font"><text:span text:style-name="T12">nets|fanout</text:span></text:span><text:span text:style-name="Default_20_Paragraph_20_Font"><text:span text:style-name="T175">|src_attr</text:span></text:span><text:span text:style-name="Default_20_Paragraph_20_Font"><text:span text:style-name="T176">|variation</text:span></text:span></text:p>
|
||||||
</table:table-cell>
|
</table:table-cell>
|
||||||
</table:table-row>
|
</table:table-row>
|
||||||
<table:table-row table:style-name="Table52.1">
|
<table:table-row table:style-name="Table52.1">
|
||||||
|
|
@ -9611,7 +9611,7 @@
|
||||||
<text:p text:style-name="P167">fields</text:p>
|
<text:p text:style-name="P167">fields</text:p>
|
||||||
</table:table-cell>
|
</table:table-cell>
|
||||||
<table:table-cell table:style-name="Table59.A2" office:value-type="string">
|
<table:table-cell table:style-name="Table59.A2" office:value-type="string">
|
||||||
<text:p text:style-name="P164"><text:span text:style-name="Default_20_Paragraph_20_Font">List of </text:span><text:span text:style-name="Default_20_Paragraph_20_Font"><text:span text:style-name="T12">capacitance|slew|input_pins|</text:span></text:span><text:span text:style-name="Default_20_Paragraph_20_Font"><text:span text:style-name="T173">hierarc</text:span></text:span><text:span text:style-name="Default_20_Paragraph_20_Font"><text:span text:style-name="T174">h</text:span></text:span><text:span text:style-name="Default_20_Paragraph_20_Font"><text:span text:style-name="T173">i</text:span></text:span><text:span text:style-name="Default_20_Paragraph_20_Font"><text:span text:style-name="T174">c</text:span></text:span><text:span text:style-name="Default_20_Paragraph_20_Font"><text:span text:style-name="T173">al_pins|</text:span></text:span><text:span text:style-name="Default_20_Paragraph_20_Font"><text:span text:style-name="T12">nets|fanout</text:span></text:span><text:span text:style-name="Default_20_Paragraph_20_Font"><text:span text:style-name="T175">|src_attr</text:span></text:span><text:span text:style-name="Default_20_Paragraph_20_Font"><text:span text:style-name="T176">|variance</text:span></text:span></text:p>
|
<text:p text:style-name="P164"><text:span text:style-name="Default_20_Paragraph_20_Font">List of </text:span><text:span text:style-name="Default_20_Paragraph_20_Font"><text:span text:style-name="T12">capacitance|slew|input_pins|</text:span></text:span><text:span text:style-name="Default_20_Paragraph_20_Font"><text:span text:style-name="T173">hierarc</text:span></text:span><text:span text:style-name="Default_20_Paragraph_20_Font"><text:span text:style-name="T174">h</text:span></text:span><text:span text:style-name="Default_20_Paragraph_20_Font"><text:span text:style-name="T173">i</text:span></text:span><text:span text:style-name="Default_20_Paragraph_20_Font"><text:span text:style-name="T174">c</text:span></text:span><text:span text:style-name="Default_20_Paragraph_20_Font"><text:span text:style-name="T173">al_pins|</text:span></text:span><text:span text:style-name="Default_20_Paragraph_20_Font"><text:span text:style-name="T12">nets|fanout</text:span></text:span><text:span text:style-name="Default_20_Paragraph_20_Font"><text:span text:style-name="T175">|src_attr</text:span></text:span><text:span text:style-name="Default_20_Paragraph_20_Font"><text:span text:style-name="T176">|variation</text:span></text:span></text:p>
|
||||||
</table:table-cell>
|
</table:table-cell>
|
||||||
</table:table-row>
|
</table:table-row>
|
||||||
<table:table-row table:style-name="Table59.1">
|
<table:table-row table:style-name="Table59.1">
|
||||||
|
|
|
||||||
BIN
doc/OpenSTA.pdf
BIN
doc/OpenSTA.pdf
Binary file not shown.
|
|
@ -384,13 +384,6 @@ Graph::makeWireEdge(const Pin *from_pin,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
Graph::makeSceneAfter()
|
|
||||||
{
|
|
||||||
ap_count_ = dcalcAnalysisPtCount();
|
|
||||||
initSlews();
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
Vertex *
|
Vertex *
|
||||||
|
|
@ -782,17 +775,13 @@ Graph::removeDelayAnnotated(Edge *edge)
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// This only gets called if the analysis type changes from single
|
|
||||||
// to bc_wc/ocv or visa versa.
|
|
||||||
void
|
void
|
||||||
Graph::setDelayCount(DcalcAPIndex ap_count)
|
Graph::delayCountChanged()
|
||||||
{
|
{
|
||||||
if (ap_count != ap_count_) {
|
ap_count_ = dcalcAnalysisPtCount();
|
||||||
// Discard any existing delays.
|
// Discard any existing delays.
|
||||||
removePeriodCheckAnnotations();
|
removePeriodCheckAnnotations();
|
||||||
ap_count_ = ap_count;
|
initSlews();
|
||||||
initSlews();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,14 @@
|
||||||
// Author Phillip Johnston
|
// Original Author: Phillip Johnston
|
||||||
// Licensed under CC0 1.0 Universal
|
// Licensed under CC0 1.0 Universal
|
||||||
// https://github.com/embeddedartistry/embedded-resources/blob/master/examples/cpp/dispatch.cpp
|
// Original source: https://github.com/embeddedartistry/embedded-resources/blob/master/examples/cpp/dispatch.cpp
|
||||||
// https://embeddedartistry.com/blog/2017/2/1/dispatch-queues?rq=dispatch
|
// Original article: https://embeddedartistry.com/blog/2017/2/1/dispatch-queues?rq=dispatch
|
||||||
|
//
|
||||||
|
// Modified for OpenSTA to use C++20 non-spinning DynamicLatch for synchronization.
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
#include <cstddef>
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
@ -16,6 +19,49 @@
|
||||||
|
|
||||||
namespace sta {
|
namespace sta {
|
||||||
|
|
||||||
|
class DynamicLatch
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit DynamicLatch(std::ptrdiff_t initial_count = 0) :
|
||||||
|
count_(initial_count)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete copy/move constructors to prevent accidental slicing/copying of atomics
|
||||||
|
DynamicLatch(const DynamicLatch&) = delete;
|
||||||
|
DynamicLatch& operator=(const DynamicLatch&) = delete;
|
||||||
|
|
||||||
|
// Increases the latch count (used when a new task is dispatched)
|
||||||
|
void
|
||||||
|
countUp()
|
||||||
|
{
|
||||||
|
count_.fetch_add(1, std::memory_order_release);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decreases the latch count and wakes waiting threads if it hits zero
|
||||||
|
void
|
||||||
|
countDown(std::ptrdiff_t n = 1)
|
||||||
|
{
|
||||||
|
if (count_.fetch_sub(n, std::memory_order_release) == n) {
|
||||||
|
count_.notify_all();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Blocks until the count reaches zero
|
||||||
|
void
|
||||||
|
wait() const
|
||||||
|
{
|
||||||
|
std::ptrdiff_t current = count_.load(std::memory_order_acquire);
|
||||||
|
while (current != 0) {
|
||||||
|
count_.wait(current, std::memory_order_acquire);
|
||||||
|
current = count_.load(std::memory_order_acquire);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
mutable std::atomic<std::ptrdiff_t> count_{0};
|
||||||
|
};
|
||||||
|
|
||||||
class DispatchQueue
|
class DispatchQueue
|
||||||
{
|
{
|
||||||
using fp_t = std::function<void(int thread)>;
|
using fp_t = std::function<void(int thread)>;
|
||||||
|
|
@ -45,7 +91,7 @@ private:
|
||||||
std::vector<std::thread> threads_;
|
std::vector<std::thread> threads_;
|
||||||
std::queue<fp_t> q_;
|
std::queue<fp_t> q_;
|
||||||
std::condition_variable cv_;
|
std::condition_variable cv_;
|
||||||
std::atomic<size_t> pending_task_count_;
|
DynamicLatch pending_task_count_latch_;
|
||||||
bool quit_ = false;
|
bool quit_ = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -63,8 +63,7 @@ public:
|
||||||
void makeGraph();
|
void makeGraph();
|
||||||
~Graph() override;
|
~Graph() override;
|
||||||
|
|
||||||
// Number of arc delays and slews from sdf or delay calculation.
|
void delayCountChanged();
|
||||||
void setDelayCount(DcalcAPIndex ap_count);
|
|
||||||
size_t slewCount();
|
size_t slewCount();
|
||||||
|
|
||||||
// Vertex functions.
|
// Vertex functions.
|
||||||
|
|
@ -178,7 +177,6 @@ public:
|
||||||
// Remove all delay and slew annotations.
|
// Remove all delay and slew annotations.
|
||||||
void removeDelaySlewAnnotations();
|
void removeDelaySlewAnnotations();
|
||||||
VertexSet ®ClkVertices() { return reg_clk_vertices_; }
|
VertexSet ®ClkVertices() { return reg_clk_vertices_; }
|
||||||
void makeSceneAfter();
|
|
||||||
|
|
||||||
static constexpr int vertex_level_bits = 24;
|
static constexpr int vertex_level_bits = 24;
|
||||||
static constexpr int vertex_level_max = (1<<vertex_level_bits)-1;
|
static constexpr int vertex_level_max = (1<<vertex_level_bits)-1;
|
||||||
|
|
|
||||||
|
|
@ -502,6 +502,8 @@ class NetworkEdit : public Network
|
||||||
public:
|
public:
|
||||||
NetworkEdit() = default;
|
NetworkEdit() = default;
|
||||||
bool isEditable() const override { return true; }
|
bool isEditable() const override { return true; }
|
||||||
|
virtual Port *makePort(Cell *cell,
|
||||||
|
std::string_view name) = 0;
|
||||||
virtual Instance *makeInstance(LibertyCell *cell,
|
virtual Instance *makeInstance(LibertyCell *cell,
|
||||||
std::string_view name,
|
std::string_view name,
|
||||||
Instance *parent) = 0;
|
Instance *parent) = 0;
|
||||||
|
|
@ -556,8 +558,6 @@ public:
|
||||||
virtual void setAttribute(Instance *instance,
|
virtual void setAttribute(Instance *instance,
|
||||||
std::string_view key,
|
std::string_view key,
|
||||||
std::string_view value) = 0;
|
std::string_view value) = 0;
|
||||||
virtual Port *makePort(Cell *cell,
|
|
||||||
std::string_view name) = 0;
|
|
||||||
virtual Port *makeBusPort(Cell *cell,
|
virtual Port *makeBusPort(Cell *cell,
|
||||||
std::string_view name,
|
std::string_view name,
|
||||||
int from_index,
|
int from_index,
|
||||||
|
|
|
||||||
|
|
@ -94,11 +94,12 @@ parseBusName(std::string_view name,
|
||||||
int &to,
|
int &to,
|
||||||
bool &subscript_wild);
|
bool &subscript_wild);
|
||||||
|
|
||||||
// Insert escapes before ch1 and ch2 in token.
|
// Insert escapes before ch1, ch2 or ch3 in token.
|
||||||
std::string
|
std::string
|
||||||
escapeChars(std::string_view token,
|
escapeChars(std::string_view token,
|
||||||
char ch1,
|
char ch1,
|
||||||
char ch2,
|
char ch2,
|
||||||
|
char ch3,
|
||||||
char escape);
|
char escape);
|
||||||
|
|
||||||
} // namespace sta
|
} // namespace sta
|
||||||
|
|
|
||||||
|
|
@ -146,8 +146,9 @@ public:
|
||||||
PathGroup *findPathGroup(const Clock *clock,
|
PathGroup *findPathGroup(const Clock *clock,
|
||||||
const MinMax *min_max) const;
|
const MinMax *min_max) const;
|
||||||
PathGroupSeq pathGroups(const PathEnd *path_end) const;
|
PathGroupSeq pathGroups(const PathEnd *path_end) const;
|
||||||
static StringSeq pathGroupNames(const PathEnd *path_end,
|
static bool inPathGroupNamed(const PathEnd *path_end,
|
||||||
const StaState *sta);
|
std::string_view path_group_name,
|
||||||
|
const StaState *sta);
|
||||||
static std::string_view asyncPathGroupName() { return async_group_name_; }
|
static std::string_view asyncPathGroupName() { return async_group_name_; }
|
||||||
static std::string_view pathDelayGroupName() { return path_delay_group_name_; }
|
static std::string_view pathDelayGroupName() { return path_delay_group_name_; }
|
||||||
static std::string_view gatedClkGroupName() { return gated_clk_group_name_; }
|
static std::string_view gatedClkGroupName() { return gated_clk_group_name_; }
|
||||||
|
|
|
||||||
|
|
@ -92,6 +92,8 @@ public:
|
||||||
int index) const override;
|
int index) const override;
|
||||||
PortMemberIterator *memberIterator(const Port *port) const override;
|
PortMemberIterator *memberIterator(const Port *port) const override;
|
||||||
bool hasMembers(const Port *port) const override;
|
bool hasMembers(const Port *port) const override;
|
||||||
|
Port *makePort(Cell *cell,
|
||||||
|
std::string_view name) override;
|
||||||
|
|
||||||
ObjectId id(const Instance *instance) const override;
|
ObjectId id(const Instance *instance) const override;
|
||||||
std::string getAttribute(const Instance *inst,
|
std::string getAttribute(const Instance *inst,
|
||||||
|
|
@ -146,6 +148,7 @@ public:
|
||||||
char pathEscape() const override;
|
char pathEscape() const override;
|
||||||
void setPathEscape(char escape) override;
|
void setPathEscape(char escape) override;
|
||||||
|
|
||||||
|
// NetworkEdit
|
||||||
bool isEditable() const override;
|
bool isEditable() const override;
|
||||||
LibertyLibrary *makeLibertyLibrary(std::string_view name,
|
LibertyLibrary *makeLibertyLibrary(std::string_view name,
|
||||||
std::string_view filename) override;
|
std::string_view filename) override;
|
||||||
|
|
@ -202,6 +205,8 @@ public:
|
||||||
const PatternMatch *pattern) const override;
|
const PatternMatch *pattern) const override;
|
||||||
std::string name(const Port *port) const override;
|
std::string name(const Port *port) const override;
|
||||||
std::string busName(const Port *port) const override;
|
std::string busName(const Port *port) const override;
|
||||||
|
Port *makePort(Cell *cell,
|
||||||
|
std::string_view name) override;
|
||||||
|
|
||||||
std::string name(const Instance *instance) const override;
|
std::string name(const Instance *instance) const override;
|
||||||
std::string pathName(const Instance *instance) const override;
|
std::string pathName(const Instance *instance) const override;
|
||||||
|
|
@ -289,5 +294,8 @@ escapeDividers(std::string_view name,
|
||||||
std::string
|
std::string
|
||||||
escapeBrackets(std::string_view name,
|
escapeBrackets(std::string_view name,
|
||||||
const Network *network);
|
const Network *network);
|
||||||
|
std::string
|
||||||
|
escapeDividerBrackets(std::string_view name,
|
||||||
|
const Network *network);
|
||||||
|
|
||||||
} // namespace sta
|
} // namespace sta
|
||||||
|
|
|
||||||
|
|
@ -353,7 +353,8 @@ public:
|
||||||
TagGroup *tagGroup(const Vertex *vertex) const;
|
TagGroup *tagGroup(const Vertex *vertex) const;
|
||||||
TagGroup *tagGroup(TagGroupIndex index) const;
|
TagGroup *tagGroup(TagGroupIndex index) const;
|
||||||
void reportArrivals(Vertex *vertex,
|
void reportArrivals(Vertex *vertex,
|
||||||
bool report_tag_index) const;
|
bool report_tag_index,
|
||||||
|
int digits) const;
|
||||||
Slack wnsSlack(Vertex *vertex,
|
Slack wnsSlack(Vertex *vertex,
|
||||||
PathAPIndex path_ap_index);
|
PathAPIndex path_ap_index);
|
||||||
void levelsChangedBefore();
|
void levelsChangedBefore();
|
||||||
|
|
|
||||||
|
|
@ -3081,7 +3081,8 @@ libertyReaderFindPort(const LibertyCell *cell,
|
||||||
char brkt_right = library->busBrktRight();
|
char brkt_right = library->busBrktRight();
|
||||||
const char escape = '\\';
|
const char escape = '\\';
|
||||||
// Pins at top level with bus names have escaped brackets.
|
// Pins at top level with bus names have escaped brackets.
|
||||||
std::string escaped_port_name = escapeChars(port_name, brkt_left, brkt_right, escape);
|
std::string escaped_port_name = escapeChars(port_name, brkt_left, brkt_right,
|
||||||
|
'\0', escape);
|
||||||
port = cell->findLibertyPort(escaped_port_name);
|
port = cell->findLibertyPort(escaped_port_name);
|
||||||
}
|
}
|
||||||
return port;
|
return port;
|
||||||
|
|
|
||||||
|
|
@ -167,9 +167,10 @@ parseBusName(std::string_view name,
|
||||||
|
|
||||||
std::string
|
std::string
|
||||||
escapeChars(std::string_view token,
|
escapeChars(std::string_view token,
|
||||||
const char ch1,
|
char ch1,
|
||||||
const char ch2,
|
char ch2,
|
||||||
const char escape)
|
char ch3,
|
||||||
|
char escape)
|
||||||
{
|
{
|
||||||
std::string escaped;
|
std::string escaped;
|
||||||
escaped.reserve(token.size());
|
escaped.reserve(token.size());
|
||||||
|
|
@ -184,7 +185,7 @@ escapeChars(std::string_view token,
|
||||||
else
|
else
|
||||||
escaped += ch;
|
escaped += ch;
|
||||||
}
|
}
|
||||||
else if (ch == ch1 || ch == ch2) {
|
else if (ch == ch1 || ch == ch2 || ch == ch3) {
|
||||||
escaped += escape;
|
escaped += escape;
|
||||||
escaped += ch;
|
escaped += ch;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -330,6 +330,13 @@ NetworkNameAdapter::memberIterator(const Port *port) const
|
||||||
return network_->memberIterator(port);
|
return network_->memberIterator(port);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Port *
|
||||||
|
NetworkNameAdapter::makePort(Cell *cell,
|
||||||
|
std::string_view name)
|
||||||
|
{
|
||||||
|
return network_edit_->makePort(cell, name);
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
ObjectId
|
ObjectId
|
||||||
|
|
@ -736,6 +743,14 @@ SdcNetwork::busName(const Port *port) const
|
||||||
return staToSdc(network_->busName(port));
|
return staToSdc(network_->busName(port));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Port *
|
||||||
|
SdcNetwork::makePort(Cell *cell,
|
||||||
|
std::string_view name)
|
||||||
|
{
|
||||||
|
std::string escaped_name = escapeDividerBrackets(name, network_edit_);
|
||||||
|
return network_edit_->makePort(cell, escaped_name);
|
||||||
|
}
|
||||||
|
|
||||||
std::string
|
std::string
|
||||||
SdcNetwork::name(const Instance *instance) const
|
SdcNetwork::name(const Instance *instance) const
|
||||||
{
|
{
|
||||||
|
|
@ -1073,7 +1088,7 @@ SdcNetwork::makeInstance(LibertyCell *cell,
|
||||||
std::string_view name,
|
std::string_view name,
|
||||||
Instance *parent)
|
Instance *parent)
|
||||||
{
|
{
|
||||||
std::string escaped_name = escapeDividers(std::string(name), this);
|
std::string escaped_name = escapeDividerBrackets(name, this);
|
||||||
return network_edit_->makeInstance(cell, escaped_name, parent);
|
return network_edit_->makeInstance(cell, escaped_name, parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1081,7 +1096,7 @@ Net *
|
||||||
SdcNetwork::makeNet(std::string_view name,
|
SdcNetwork::makeNet(std::string_view name,
|
||||||
Instance *parent)
|
Instance *parent)
|
||||||
{
|
{
|
||||||
std::string escaped_name = escapeDividers(std::string(name), this);
|
std::string escaped_name = escapeDividerBrackets(name, this);
|
||||||
return network_edit_->makeNet(escaped_name, parent);
|
return network_edit_->makeNet(escaped_name, parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1254,11 +1269,19 @@ SdcNetwork::visitMatches(const Instance *parent,
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
std::string
|
||||||
|
escapeDividerBrackets(std::string_view name,
|
||||||
|
const Network *network)
|
||||||
|
{
|
||||||
|
return escapeChars(name, network->pathDivider(), '[', ']',
|
||||||
|
network->pathEscape());
|
||||||
|
}
|
||||||
|
|
||||||
std::string
|
std::string
|
||||||
escapeDividers(std::string_view name,
|
escapeDividers(std::string_view name,
|
||||||
const Network *network)
|
const Network *network)
|
||||||
{
|
{
|
||||||
return escapeChars(name, network->pathDivider(), '\0',
|
return escapeChars(name, network->pathDivider(), '\0', '\0',
|
||||||
network->pathEscape());
|
network->pathEscape());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1266,7 +1289,7 @@ std::string
|
||||||
escapeBrackets(std::string_view name,
|
escapeBrackets(std::string_view name,
|
||||||
const Network *network)
|
const Network *network)
|
||||||
{
|
{
|
||||||
return escapeChars(name, '[', ']', network->pathEscape());
|
return escapeChars(name, '[', ']', '\0', network->pathEscape());
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace sta
|
} // namespace sta
|
||||||
|
|
|
||||||
|
|
@ -474,23 +474,23 @@ PathGroups::pathGroups(const PathEnd *path_end) const
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mirrors PathGroups::pathGroup.
|
// Mirrors PathGroups::pathGroup.
|
||||||
StringSeq
|
bool
|
||||||
PathGroups::pathGroupNames(const PathEnd *path_end,
|
PathGroups::inPathGroupNamed(const PathEnd *path_end,
|
||||||
const StaState *sta)
|
std::string_view path_group_name,
|
||||||
|
const StaState *sta)
|
||||||
{
|
{
|
||||||
StringSeq group_names;
|
|
||||||
std::string group_name;
|
|
||||||
const Search *search = sta->search();
|
const Search *search = sta->search();
|
||||||
ExceptionPathSeq group_paths = search->groupPathsTo(path_end);
|
ExceptionPathSeq group_paths = search->groupPathsTo(path_end);
|
||||||
if (path_end->isUnconstrained())
|
if (path_end->isUnconstrained())
|
||||||
group_name = unconstrained_group_name_;
|
return path_group_name == unconstrained_group_name_;
|
||||||
else if (!group_paths.empty()) {
|
else if (!group_paths.empty()) {
|
||||||
// GroupPaths have precedence.
|
// GroupPaths have precedence.
|
||||||
for (ExceptionPath *group_path : group_paths) {
|
for (ExceptionPath *group_path : group_paths) {
|
||||||
if (group_path->isDefault())
|
std::string_view group_name = group_path->isDefault()
|
||||||
group_names.emplace_back(path_delay_group_name_);
|
? path_delay_group_name_
|
||||||
else
|
: group_path->name();
|
||||||
group_names.emplace_back(group_path->name());
|
if (path_group_name == group_name)
|
||||||
|
return true;;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (path_end->isCheck() || path_end->isLatchCheck()) {
|
else if (path_end->isCheck() || path_end->isLatchCheck()) {
|
||||||
|
|
@ -498,18 +498,18 @@ PathGroups::pathGroupNames(const PathEnd *path_end,
|
||||||
const Clock *tgt_clk = path_end->targetClk(sta);
|
const Clock *tgt_clk = path_end->targetClk(sta);
|
||||||
if (check_role == TimingRole::removal()
|
if (check_role == TimingRole::removal()
|
||||||
|| check_role == TimingRole::recovery())
|
|| check_role == TimingRole::recovery())
|
||||||
group_name = async_group_name_;
|
return path_group_name == async_group_name_;
|
||||||
else
|
else
|
||||||
group_name = tgt_clk->name();
|
return path_group_name == tgt_clk->name();
|
||||||
}
|
}
|
||||||
else if (path_end->isOutputDelay()
|
else if (path_end->isOutputDelay()
|
||||||
|| path_end->isDataCheck()) {
|
|| path_end->isDataCheck()) {
|
||||||
const Clock *tgt_clk = path_end->targetClk(sta);
|
const Clock *tgt_clk = path_end->targetClk(sta);
|
||||||
if (tgt_clk)
|
if (tgt_clk)
|
||||||
group_name = tgt_clk->name();
|
return path_group_name == tgt_clk->name();
|
||||||
}
|
}
|
||||||
else if (path_end->isGatedClock())
|
else if (path_end->isGatedClock())
|
||||||
group_name = gated_clk_group_name_;
|
return path_group_name == gated_clk_group_name_;
|
||||||
else if (path_end->isPathDelay()) {
|
else if (path_end->isPathDelay()) {
|
||||||
// Path delays that end at timing checks are part of the target clk group
|
// Path delays that end at timing checks are part of the target clk group
|
||||||
// unless -ignore_clock_latency is true.
|
// unless -ignore_clock_latency is true.
|
||||||
|
|
@ -517,13 +517,11 @@ PathGroups::pathGroupNames(const PathEnd *path_end,
|
||||||
const Clock *tgt_clk = path_end->targetClk(sta);
|
const Clock *tgt_clk = path_end->targetClk(sta);
|
||||||
if (tgt_clk
|
if (tgt_clk
|
||||||
&& !path_delay->ignoreClkLatency())
|
&& !path_delay->ignoreClkLatency())
|
||||||
group_name = tgt_clk->name();
|
return path_group_name == tgt_clk->name();
|
||||||
else
|
else
|
||||||
group_name = path_delay_group_name_;
|
return path_group_name == path_delay_group_name_;
|
||||||
}
|
}
|
||||||
if (!group_name.empty())
|
return false;
|
||||||
group_names.push_back(group_name);
|
|
||||||
return group_names;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GroupPath *
|
GroupPath *
|
||||||
|
|
|
||||||
|
|
@ -2754,7 +2754,8 @@ ReportPathLess::operator()(const Path *path1,
|
||||||
|
|
||||||
void
|
void
|
||||||
Search::reportArrivals(Vertex *vertex,
|
Search::reportArrivals(Vertex *vertex,
|
||||||
bool report_tag_index) const
|
bool report_tag_index,
|
||||||
|
int digits) const
|
||||||
{
|
{
|
||||||
report_->report("Vertex {}", vertex->to_string(this));
|
report_->report("Vertex {}", vertex->to_string(this));
|
||||||
TagGroup *tag_group = tagGroup(vertex);
|
TagGroup *tag_group = tagGroup(vertex);
|
||||||
|
|
@ -2771,7 +2772,6 @@ Search::reportArrivals(Vertex *vertex,
|
||||||
for (const Path *path : paths) {
|
for (const Path *path : paths) {
|
||||||
const Tag *tag = path->tag(this);
|
const Tag *tag = path->tag(this);
|
||||||
const RiseFall *rf = tag->transition();
|
const RiseFall *rf = tag->transition();
|
||||||
std::string req = delayAsString(path->required(), this);
|
|
||||||
bool report_prev = false;
|
bool report_prev = false;
|
||||||
std::string prev_str;
|
std::string prev_str;
|
||||||
if (report_prev) {
|
if (report_prev) {
|
||||||
|
|
@ -2791,7 +2791,8 @@ Search::reportArrivals(Vertex *vertex,
|
||||||
}
|
}
|
||||||
report_->report(" {} {} {} / {} {}{}", rf->shortName(),
|
report_->report(" {} {} {} / {} {}{}", rf->shortName(),
|
||||||
path->minMax(this)->to_string(),
|
path->minMax(this)->to_string(),
|
||||||
delayAsString(path->arrival(), this), req,
|
delayAsString(path->arrival(), digits, this),
|
||||||
|
delayAsString(path->required(), digits, this),
|
||||||
tag->to_string(report_tag_index, false, this), prev_str);
|
tag->to_string(report_tag_index, false, this), prev_str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -269,9 +269,10 @@ report_tag_groups()
|
||||||
|
|
||||||
void
|
void
|
||||||
report_tag_arrivals_cmd(Vertex *vertex,
|
report_tag_arrivals_cmd(Vertex *vertex,
|
||||||
bool report_tag_index)
|
bool report_tag_index,
|
||||||
|
int digits)
|
||||||
{
|
{
|
||||||
Sta::sta()->search()->reportArrivals(vertex, report_tag_index);
|
Sta::sta()->search()->reportArrivals(vertex, report_tag_index, digits);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
||||||
|
|
@ -333,7 +333,7 @@ define_cmd_args "report_checks" \
|
||||||
[-sort_by_slack]\
|
[-sort_by_slack]\
|
||||||
[-path_group group_name]\
|
[-path_group group_name]\
|
||||||
[-format full|full_clock|full_clock_expanded|short|end|slack_only|summary|json]\
|
[-format full|full_clock|full_clock_expanded|short|end|slack_only|summary|json]\
|
||||||
[-fields capacitance|slew|fanout|input_pin|net|src_attr]\
|
[-fields capacitance|slew|fanout|input_pin|net|src_attr|variation]\
|
||||||
[-digits digits]\
|
[-digits digits]\
|
||||||
[-no_line_splits]\
|
[-no_line_splits]\
|
||||||
[> filename] [>> filename]}
|
[> filename] [>> filename]}
|
||||||
|
|
@ -805,10 +805,19 @@ proc report_slack { args } {
|
||||||
################################################################
|
################################################################
|
||||||
|
|
||||||
# Internal debugging command.
|
# Internal debugging command.
|
||||||
proc report_tag_arrivals { pin } {
|
proc report_tag_arrivals { args } {
|
||||||
set pin [get_port_pin_error "pin" $pin]
|
global sta_report_default_digits
|
||||||
|
|
||||||
|
parse_key_args "report_tag_arrivals" args keys {-digits} flags {}
|
||||||
|
set pin [get_port_pin_error "pin" [lindex $args 0]]
|
||||||
|
if [info exists keys(-digits)] {
|
||||||
|
set digits $keys(-digits)
|
||||||
|
check_positive_integer "-digits" $digits
|
||||||
|
} else {
|
||||||
|
set digits $sta_report_default_digits
|
||||||
|
}
|
||||||
foreach vertex [$pin vertices] {
|
foreach vertex [$pin vertices] {
|
||||||
report_tag_arrivals_cmd $vertex 1
|
report_tag_arrivals_cmd $vertex 1 $digits
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -805,7 +805,7 @@ Sta::setAnalysisType(AnalysisType analysis_type,
|
||||||
delaysInvalid();
|
delaysInvalid();
|
||||||
search_->deletePathGroups();
|
search_->deletePathGroups();
|
||||||
if (graph_)
|
if (graph_)
|
||||||
graph_->setDelayCount(dcalcAnalysisPtCount());
|
graph_->delayCountChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2311,6 +2311,8 @@ Sta::setPocvMode(PocvMode mode)
|
||||||
}
|
}
|
||||||
updateComponentsState();
|
updateComponentsState();
|
||||||
delaysInvalid();
|
delaysInvalid();
|
||||||
|
if (graph_)
|
||||||
|
graph_->delayCountChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2554,7 +2556,7 @@ Sta::makeScenes(const StringSeq &scene_names)
|
||||||
cmd_scene_ = scenes_[0];
|
cmd_scene_ = scenes_[0];
|
||||||
updateComponentsState();
|
updateComponentsState();
|
||||||
if (graph_)
|
if (graph_)
|
||||||
graph_->makeSceneAfter();
|
graph_->delayCountChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -2583,7 +2585,7 @@ Sta::makeScene(const std::string &name,
|
||||||
Scene *scene = makeScene(name, mode, parasitics_min, parasitics_max);
|
Scene *scene = makeScene(name, mode, parasitics_min, parasitics_max);
|
||||||
updateComponentsState();
|
updateComponentsState();
|
||||||
if (graph_)
|
if (graph_)
|
||||||
graph_->makeSceneAfter();
|
graph_->delayCountChanged();
|
||||||
updateSceneLiberty(scene, liberty_min_files, liberty_max_files);
|
updateSceneLiberty(scene, liberty_min_files, liberty_max_files);
|
||||||
cmd_scene_ = scene;
|
cmd_scene_ = scene;
|
||||||
}
|
}
|
||||||
|
|
@ -3304,15 +3306,11 @@ EndpointPathEndVisitor::copy() const
|
||||||
void
|
void
|
||||||
EndpointPathEndVisitor::visit(PathEnd *path_end)
|
EndpointPathEndVisitor::visit(PathEnd *path_end)
|
||||||
{
|
{
|
||||||
if (path_end->minMax(sta_) == min_max_) {
|
if (path_end->minMax(sta_) == min_max_
|
||||||
StringSeq group_names = PathGroups::pathGroupNames(path_end, sta_);
|
&& PathGroups::inPathGroupNamed(path_end, path_group_name_, sta_)) {
|
||||||
for (std::string &group_name : group_names) {
|
Slack end_slack = path_end->slack(sta_);
|
||||||
if (group_name == path_group_name_) {
|
if (delayLess(end_slack, slack_, sta_))
|
||||||
Slack end_slack = path_end->slack(sta_);
|
slack_ = end_slack;
|
||||||
if (delayLess(end_slack, slack_, sta_))
|
|
||||||
slack_ = end_slack;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -4437,7 +4435,8 @@ Sta::makeNet(const char *name,
|
||||||
Instance *parent)
|
Instance *parent)
|
||||||
{
|
{
|
||||||
NetworkEdit *network = networkCmdEdit();
|
NetworkEdit *network = networkCmdEdit();
|
||||||
Net *net = network->makeNet(name, parent);
|
std::string escaped = escapeBrackets(name, network);
|
||||||
|
Net *net = network->makeNet(escaped, parent);
|
||||||
// Sta notification unnecessary.
|
// Sta notification unnecessary.
|
||||||
return net;
|
return net;
|
||||||
}
|
}
|
||||||
|
|
@ -4485,8 +4484,9 @@ Sta::makePortPin(const char *port_name,
|
||||||
ensureLinked();
|
ensureLinked();
|
||||||
NetworkReader *network = dynamic_cast<NetworkReader *>(network_);
|
NetworkReader *network = dynamic_cast<NetworkReader *>(network_);
|
||||||
Instance *top_inst = network->topInstance();
|
Instance *top_inst = network->topInstance();
|
||||||
|
std::string escaped = escapeBrackets(port_name, network);
|
||||||
Cell *top_cell = network->cell(top_inst);
|
Cell *top_cell = network->cell(top_inst);
|
||||||
Port *port = network->makePort(top_cell, port_name);
|
Port *port = network->makePort(top_cell, escaped);
|
||||||
network->setDirection(port, dir);
|
network->setDirection(port, dir);
|
||||||
Pin *pin = network->makePin(top_inst, port, nullptr);
|
Pin *pin = network->makePin(top_inst, port, nullptr);
|
||||||
makePortPinAfter(pin);
|
makePortPinAfter(pin);
|
||||||
|
|
|
||||||
|
|
@ -1838,7 +1838,7 @@ TEST_F(StaDesignTest, SearchReportArrivals) {
|
||||||
Search *search = sta_->search();
|
Search *search = sta_->search();
|
||||||
Vertex *v = findVertex("r1/Q");
|
Vertex *v = findVertex("r1/Q");
|
||||||
ASSERT_NE(v, nullptr);
|
ASSERT_NE(v, nullptr);
|
||||||
search->reportArrivals(v, false);
|
search->reportArrivals(v, false, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Search: reportPathCountHistogram ---
|
// --- Search: reportPathCountHistogram ---
|
||||||
|
|
@ -4143,8 +4143,8 @@ TEST_F(StaDesignTest, SearchReportArrivals2) {
|
||||||
Search *search = sta_->search();
|
Search *search = sta_->search();
|
||||||
Vertex *v = findVertex("r1/Q");
|
Vertex *v = findVertex("r1/Q");
|
||||||
ASSERT_NE(v, nullptr);
|
ASSERT_NE(v, nullptr);
|
||||||
search->reportArrivals(v, false);
|
search->reportArrivals(v, false, 3);
|
||||||
search->reportArrivals(v, true);
|
search->reportArrivals(v, true, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(StaDesignTest, SearchSeedArrival) {
|
TEST_F(StaDesignTest, SearchSeedArrival) {
|
||||||
|
|
|
||||||
|
|
@ -97,8 +97,8 @@ puts "paths: [sta::path_count]"
|
||||||
puts "--- report_tag_arrivals ---"
|
puts "--- report_tag_arrivals ---"
|
||||||
set v [sta::worst_slack_vertex max]
|
set v [sta::worst_slack_vertex max]
|
||||||
if { $v != "NULL" } {
|
if { $v != "NULL" } {
|
||||||
sta::report_tag_arrivals_cmd $v 1
|
sta::report_tag_arrivals_cmd $v 1 3
|
||||||
sta::report_tag_arrivals_cmd $v 0
|
sta::report_tag_arrivals_cmd $v 0 3
|
||||||
}
|
}
|
||||||
|
|
||||||
############################################################
|
############################################################
|
||||||
|
|
|
||||||
|
|
@ -86,8 +86,8 @@ if { $wv != "NULL" } {
|
||||||
}
|
}
|
||||||
|
|
||||||
# report_tag_arrivals
|
# report_tag_arrivals
|
||||||
sta::report_tag_arrivals_cmd $wv 1
|
sta::report_tag_arrivals_cmd $wv 1 3
|
||||||
sta::report_tag_arrivals_cmd $wv 0
|
sta::report_tag_arrivals_cmd $wv 0 3
|
||||||
}
|
}
|
||||||
|
|
||||||
puts "--- worst_slack_vertex min ---"
|
puts "--- worst_slack_vertex min ---"
|
||||||
|
|
|
||||||
|
|
@ -169,6 +169,7 @@ record_public_tests {
|
||||||
verilog_well_supplies
|
verilog_well_supplies
|
||||||
verilog_specify
|
verilog_specify
|
||||||
verilog_write_escape
|
verilog_write_escape
|
||||||
|
verilog_write_gzip
|
||||||
verilog_unconnected_hpin
|
verilog_unconnected_hpin
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
module top (in1,
|
||||||
|
in2,
|
||||||
|
clk1,
|
||||||
|
clk2,
|
||||||
|
clk3,
|
||||||
|
out);
|
||||||
|
input in1;
|
||||||
|
input in2;
|
||||||
|
input clk1;
|
||||||
|
input clk2;
|
||||||
|
input clk3;
|
||||||
|
output out;
|
||||||
|
|
||||||
|
wire r1q;
|
||||||
|
wire r2q;
|
||||||
|
wire u1z;
|
||||||
|
wire u2z;
|
||||||
|
|
||||||
|
DFFHQx4_ASAP7_75t_R r1 (.Q(r1q),
|
||||||
|
.CLK(clk1),
|
||||||
|
.D(in1));
|
||||||
|
DFFHQx4_ASAP7_75t_R r2 (.Q(r2q),
|
||||||
|
.CLK(clk2),
|
||||||
|
.D(in2));
|
||||||
|
DFFHQx4_ASAP7_75t_R r3 (.Q(out),
|
||||||
|
.CLK(clk3),
|
||||||
|
.D(u2z));
|
||||||
|
BUFx2_ASAP7_75t_R u1 (.Y(u1z),
|
||||||
|
.A(r2q));
|
||||||
|
AND2x2_ASAP7_75t_R u2 (.Y(u2z),
|
||||||
|
.A(r1q),
|
||||||
|
.B(u1z));
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
# Check that write_verilog supports gzip compression natively if .gz extension is provided.
|
||||||
|
source helpers.tcl
|
||||||
|
read_liberty asap7_small.lib.gz
|
||||||
|
read_verilog reg1_asap7.v
|
||||||
|
link_design top
|
||||||
|
set verilog_file [make_result_file "verilog_write_gzip.v.gz"]
|
||||||
|
write_verilog $verilog_file
|
||||||
|
report_file $verilog_file
|
||||||
|
|
@ -1,15 +1,16 @@
|
||||||
// Author Phillip Johnston
|
// Original Author: Phillip Johnston
|
||||||
// Licensed under CC0 1.0 Universal
|
// Licensed under CC0 1.0 Universal
|
||||||
// https://github.com/embeddedartistry/embedded-resources/blob/master/examples/cpp/dispatch.cpp
|
// Original source: https://github.com/embeddedartistry/embedded-resources/blob/master/examples/cpp/dispatch.cpp
|
||||||
// https://embeddedartistry.com/blog/2017/2/1/dispatch-queues?rq=dispatch
|
// Original article: https://embeddedartistry.com/blog/2017/2/1/dispatch-queues?rq=dispatch
|
||||||
|
//
|
||||||
|
// Modified for OpenSTA to use C++20 non-spinning DynamicLatch for synchronization.
|
||||||
|
|
||||||
#include "DispatchQueue.hh"
|
#include "DispatchQueue.hh"
|
||||||
|
|
||||||
namespace sta {
|
namespace sta {
|
||||||
|
|
||||||
DispatchQueue::DispatchQueue(size_t thread_count) :
|
DispatchQueue::DispatchQueue(size_t thread_count) :
|
||||||
threads_(thread_count),
|
threads_(thread_count)
|
||||||
pending_task_count_(0)
|
|
||||||
{
|
{
|
||||||
for(size_t i = 0; i < thread_count; i++)
|
for(size_t i = 0; i < thread_count; i++)
|
||||||
threads_[i] = std::thread(&DispatchQueue::dispatch_thread_handler, this, i);
|
threads_[i] = std::thread(&DispatchQueue::dispatch_thread_handler, this, i);
|
||||||
|
|
@ -58,8 +59,7 @@ DispatchQueue::getThreadCount() const
|
||||||
void
|
void
|
||||||
DispatchQueue::finishTasks()
|
DispatchQueue::finishTasks()
|
||||||
{
|
{
|
||||||
while (pending_task_count_.load(std::memory_order_acquire) != 0)
|
pending_task_count_latch_.wait();
|
||||||
std::this_thread::yield();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -67,7 +67,7 @@ DispatchQueue::dispatch(const fp_t& op)
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lock(lock_);
|
std::unique_lock<std::mutex> lock(lock_);
|
||||||
q_.push(op);
|
q_.push(op);
|
||||||
pending_task_count_++;
|
pending_task_count_latch_.countUp();
|
||||||
|
|
||||||
// Manual unlocking is done before notifying, to avoid waking up
|
// Manual unlocking is done before notifying, to avoid waking up
|
||||||
// the waiting thread only to block again (see notify_one for details)
|
// the waiting thread only to block again (see notify_one for details)
|
||||||
|
|
@ -80,7 +80,7 @@ DispatchQueue::dispatch(fp_t&& op)
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lock(lock_);
|
std::unique_lock<std::mutex> lock(lock_);
|
||||||
q_.push(std::move(op));
|
q_.push(std::move(op));
|
||||||
pending_task_count_++;
|
pending_task_count_latch_.countUp();
|
||||||
|
|
||||||
// Manual unlocking is done before notifying, to avoid waking up
|
// Manual unlocking is done before notifying, to avoid waking up
|
||||||
// the waiting thread only to block again (see notify_one for details)
|
// the waiting thread only to block again (see notify_one for details)
|
||||||
|
|
@ -106,7 +106,7 @@ DispatchQueue::dispatch_thread_handler(size_t i)
|
||||||
|
|
||||||
op(i);
|
op(i);
|
||||||
|
|
||||||
pending_task_count_--;
|
pending_task_count_latch_.countDown();
|
||||||
lock.lock();
|
lock.lock();
|
||||||
}
|
}
|
||||||
} while (!quit_);
|
} while (!quit_);
|
||||||
|
|
|
||||||
|
|
@ -242,13 +242,8 @@ stmt_seq:
|
||||||
continuous_assign
|
continuous_assign
|
||||||
;
|
;
|
||||||
|
|
||||||
/* specify blocks are used by some comercial tools to convey macro timing
|
// Specify blocks are used by some comercial tools to convey macro timing
|
||||||
* and other metadata.
|
// and other metadata.
|
||||||
* Their presence is not forbidden in structural verilog, this is a placeholder
|
|
||||||
* that just ignores them and allows verilog processing to proceed
|
|
||||||
* <<TODO>> if someone in the future wants implement support for timing info
|
|
||||||
* via specify blocks, implement proper parsing here
|
|
||||||
*/
|
|
||||||
specify_block:
|
specify_block:
|
||||||
SPECIFY specify_stmts ENDSPECIFY
|
SPECIFY specify_stmts ENDSPECIFY
|
||||||
{ $$ = nullptr; }
|
{ $$ = nullptr; }
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@
|
||||||
#include "Error.hh"
|
#include "Error.hh"
|
||||||
#include "Format.hh"
|
#include "Format.hh"
|
||||||
#include "Liberty.hh"
|
#include "Liberty.hh"
|
||||||
|
#include "Zlib.hh"
|
||||||
#include "Network.hh"
|
#include "Network.hh"
|
||||||
#include "NetworkCmp.hh"
|
#include "NetworkCmp.hh"
|
||||||
#include "ParseBus.hh"
|
#include "ParseBus.hh"
|
||||||
|
|
@ -47,7 +48,7 @@ public:
|
||||||
VerilogWriter(const char *filename,
|
VerilogWriter(const char *filename,
|
||||||
bool include_pwr_gnd,
|
bool include_pwr_gnd,
|
||||||
CellSeq *remove_cells,
|
CellSeq *remove_cells,
|
||||||
FILE *stream,
|
gzFile stream,
|
||||||
Network *network);
|
Network *network);
|
||||||
void writeModules();
|
void writeModules();
|
||||||
|
|
||||||
|
|
@ -82,7 +83,7 @@ protected:
|
||||||
const char *filename_;
|
const char *filename_;
|
||||||
bool include_pwr_gnd_;
|
bool include_pwr_gnd_;
|
||||||
CellSet remove_cells_;
|
CellSet remove_cells_;
|
||||||
FILE *stream_;
|
gzFile stream_;
|
||||||
Network *network_;
|
Network *network_;
|
||||||
int unconnected_net_index_{1};
|
int unconnected_net_index_{1};
|
||||||
};
|
};
|
||||||
|
|
@ -94,12 +95,13 @@ writeVerilog(const char *filename,
|
||||||
Network *network)
|
Network *network)
|
||||||
{
|
{
|
||||||
if (network->topInstance()) {
|
if (network->topInstance()) {
|
||||||
FILE *stream = fopen(filename, "w");
|
bool gzip = std::string_view(filename).ends_with(".gz");
|
||||||
|
gzFile stream = gzopen(filename, gzip ? "wb" : "wT");
|
||||||
if (stream) {
|
if (stream) {
|
||||||
VerilogWriter writer(filename, include_pwr_gnd,
|
VerilogWriter writer(filename, include_pwr_gnd,
|
||||||
remove_cells, stream, network);
|
remove_cells, stream, network);
|
||||||
writer.writeModules();
|
writer.writeModules();
|
||||||
fclose(stream);
|
gzclose(stream);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
throw FileNotWritable(filename);
|
throw FileNotWritable(filename);
|
||||||
|
|
@ -109,7 +111,7 @@ writeVerilog(const char *filename,
|
||||||
VerilogWriter::VerilogWriter(const char *filename,
|
VerilogWriter::VerilogWriter(const char *filename,
|
||||||
bool include_pwr_gnd,
|
bool include_pwr_gnd,
|
||||||
CellSeq *remove_cells,
|
CellSeq *remove_cells,
|
||||||
FILE *stream,
|
gzFile stream,
|
||||||
Network *network) :
|
Network *network) :
|
||||||
filename_(filename),
|
filename_(filename),
|
||||||
include_pwr_gnd_(include_pwr_gnd),
|
include_pwr_gnd_(include_pwr_gnd),
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue