mirror of https://github.com/YosysHQ/yosys.git
Merge branch 'main' of github.com:silimate/yosys into sim
This commit is contained in:
commit
2bb46d0453
|
|
@ -35,14 +35,14 @@ runs:
|
|||
if: runner.os == 'Linux'
|
||||
uses: awalsh128/cache-apt-pkgs-action@v1.6.0
|
||||
with:
|
||||
packages: gawk git make python3 bison clang flex libffi-dev libfl-dev libreadline-dev pkg-config tcl-dev zlib1g-dev libnsl-dev libdwarf-dev libelf-dev elfutils libdw-dev ccache
|
||||
packages: gawk git make python3 bison clang flex libffi-dev libfl-dev libreadline-dev pkg-config tcl-dev zlib1g-dev libnsl-dev libdwarf-dev libelf-dev elfutils libdw-dev ccache
|
||||
version: ${{ inputs.runs-on }}-commonys
|
||||
|
||||
- name: Linux build dependencies
|
||||
if: runner.os == 'Linux' && inputs.get-build-deps == 'true'
|
||||
uses: awalsh128/cache-apt-pkgs-action@v1.6.0
|
||||
with:
|
||||
packages: bison clang flex libffi-dev libfl-dev libreadline-dev pkg-config tcl-dev zlib1g-dev libgtest-dev
|
||||
packages: gawk git make python3 bison clang flex libffi-dev libfl-dev libreadline-dev pkg-config tcl-dev zlib1g-dev libnsl-dev libdwarf-dev libelf-dev elfutils libdw-dev ccache libgtest-dev
|
||||
version: ${{ inputs.runs-on }}-buildys
|
||||
|
||||
- name: Linux docs dependencies
|
||||
|
|
|
|||
|
|
@ -0,0 +1,230 @@
|
|||
name: Release (pyosys wheels)
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
build-linux-wheel:
|
||||
runs-on: ubuntu-latest
|
||||
name: Build Linux amd64 wheel (musl)
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: recursive
|
||||
ssh-key: ${{ secrets.SSH_PRIVATE_KEY }}
|
||||
|
||||
- name: Build wheel in Alpine container
|
||||
run: |
|
||||
docker run --rm \
|
||||
-v "${{ github.workspace }}:/src" \
|
||||
-w /src \
|
||||
--platform linux/amd64 \
|
||||
alpine:3.20 sh -c '
|
||||
set -ex
|
||||
apk add --no-cache \
|
||||
build-base bison flex flex-dev gperf \
|
||||
tcl-dev readline-dev zlib-dev libffi-dev \
|
||||
libdwarf-dev elfutils-dev \
|
||||
python3 python3-dev py3-pip py3-setuptools py3-wheel \
|
||||
git pkgconf ccache
|
||||
|
||||
git config --global --add safe.directory /src
|
||||
git submodule foreach --recursive git config --global --add safe.directory \$toplevel/\$sm_path
|
||||
|
||||
# Alpine/musl compatibility shims for Verific tclmain link step
|
||||
ln -sf /usr/lib/libtcl8.6.so /usr/lib/libtcl.so
|
||||
echo "void dummy_nsl(void){}" | gcc -shared -o /usr/lib/libnsl.so -x c -
|
||||
|
||||
# Build Verific TCL main (needed before Yosys)
|
||||
cd /src/verific/tclmain
|
||||
make
|
||||
cd /src
|
||||
|
||||
# Build the wheel via setup.py
|
||||
pip install --break-system-packages pybind11 cxxheaderparser
|
||||
_PYOSYS_OVERRIDE_VER=$(
|
||||
grep "^YOSYS_VER " Makefile | head -1 | sed "s/.*:= *//" | tr "+" "."
|
||||
) python3 setup.py bdist_wheel --dist-dir /src/dist
|
||||
'
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: linux-musl-wheel
|
||||
path: dist/*.whl
|
||||
|
||||
build-manylinux-wheel:
|
||||
runs-on: ubuntu-latest
|
||||
name: Build Linux amd64 wheel (manylinux2014, glibc 2.17+)
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: recursive
|
||||
ssh-key: ${{ secrets.SSH_PRIVATE_KEY }}
|
||||
|
||||
- name: Build wheel in manylinux2014 container
|
||||
run: |
|
||||
docker run --rm \
|
||||
-v "${{ github.workspace }}:/src" \
|
||||
-w /src \
|
||||
--platform linux/amd64 \
|
||||
quay.io/pypa/manylinux2014_x86_64 bash -c '
|
||||
set -ex
|
||||
|
||||
yum install -y tcl-devel readline-devel zlib-devel libffi-devel \
|
||||
flex gperf ccache patchelf \
|
||||
elfutils-devel elfutils-libelf-devel libdwarf-devel
|
||||
|
||||
# Build bison >= 3.x from source
|
||||
curl -L https://ftp.gnu.org/gnu/bison/bison-3.8.2.tar.gz | tar -xzC /tmp
|
||||
cd /tmp/bison-3.8.2 && ./configure && make -j$(nproc) && make install
|
||||
cd /src
|
||||
|
||||
# Use the manylinux2014 Python 3.13
|
||||
export PATH=/opt/python/cp313-cp313/bin:$PATH
|
||||
|
||||
git config --global --add safe.directory /src
|
||||
git submodule foreach --recursive git config --global --add safe.directory \$toplevel/\$sm_path
|
||||
|
||||
# musl/manylinux compatibility shim for Verific tclmain link step
|
||||
echo "void dummy_nsl(void){}" | gcc -shared -o /usr/lib64/libnsl.so -x c - || true
|
||||
|
||||
# Build Verific TCL main
|
||||
cd /src/verific/tclmain
|
||||
make
|
||||
cd /src
|
||||
|
||||
pip3 install --upgrade pip setuptools wheel pybind11 cxxheaderparser
|
||||
|
||||
_PYOSYS_OVERRIDE_VER=$(
|
||||
grep "^YOSYS_VER " Makefile | head -1 | sed "s/.*:= *//" | tr "+" "."
|
||||
) python3 setup.py bdist_wheel --dist-dir /src/dist-manylinux
|
||||
|
||||
# Tag wheel as manylinux2014
|
||||
pip3 install auditwheel || true
|
||||
for whl in /src/dist-manylinux/*.whl; do
|
||||
auditwheel repair "$whl" --plat manylinux2014_x86_64 -w /src/dist-manylinux/ 2>/dev/null || true
|
||||
done
|
||||
'
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: linux-manylinux-wheel
|
||||
path: dist-manylinux/*.whl
|
||||
|
||||
build-macos-wheel:
|
||||
runs-on: macos-15
|
||||
name: Build macOS arm64 wheel
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: recursive
|
||||
ssh-key: ${{ secrets.SSH_PRIVATE_KEY }}
|
||||
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.13'
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
brew install bison flex gperf tcl-tk@8 readline libffi dwarfutils libelf ccache
|
||||
pip3 install pybind11 cxxheaderparser setuptools wheel
|
||||
|
||||
- name: Build Verific tclmain
|
||||
run: |
|
||||
export PATH="$(brew --prefix bison)/bin:$(brew --prefix flex)/bin:$PATH"
|
||||
export MACOSX_DEPLOYMENT_TARGET=11.0
|
||||
cd verific/tclmain
|
||||
make
|
||||
|
||||
- name: Build wheel
|
||||
run: |
|
||||
export PATH="$(brew --prefix bison)/bin:$(brew --prefix flex)/bin:$PATH"
|
||||
export MACOSX_DEPLOYMENT_TARGET=11.0
|
||||
_PYOSYS_OVERRIDE_VER=$(
|
||||
grep "^YOSYS_VER " Makefile | head -1 | sed "s/.*:= *//" | tr "+" "."
|
||||
) python3 setup.py bdist_wheel --dist-dir dist
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: macos-wheel
|
||||
path: dist/*.whl
|
||||
|
||||
release:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [build-linux-wheel, build-manylinux-wheel, build-macos-wheel]
|
||||
name: Create GitHub releases
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: all-wheels
|
||||
merge-multiple: true
|
||||
|
||||
- name: Generate release notes
|
||||
id: meta
|
||||
run: |
|
||||
SHORT_SHA=$(git rev-parse --short HEAD)
|
||||
FULL_SHA=$(git rev-parse HEAD)
|
||||
DATE=$(date -u +%Y-%m-%d)
|
||||
echo "short_sha=$SHORT_SHA" >> "$GITHUB_OUTPUT"
|
||||
echo "date=$DATE" >> "$GITHUB_OUTPUT"
|
||||
REPO_URL="${{ github.server_url }}/${{ github.repository }}"
|
||||
printf '%s\n' \
|
||||
"Automated build from \`main\` @ [\`${SHORT_SHA}\`](${REPO_URL}/commit/${FULL_SHA})" \
|
||||
"" \
|
||||
"**Built:** ${DATE}" \
|
||||
"" \
|
||||
"### Assets" \
|
||||
"| File | Platform |" \
|
||||
"|------|----------|" \
|
||||
"| \`pyosys-*-linux_x86_64.whl\` | Linux x86-64 (musl) |" \
|
||||
"| \`pyosys-*-manylinux2014*.whl\` | Linux x86-64 (manylinux2014, glibc 2.17+) |" \
|
||||
"| \`pyosys-*-macosx_*_arm64.whl\` | macOS Apple Silicon |" \
|
||||
"" \
|
||||
"### Installation" \
|
||||
"\`\`\`bash" \
|
||||
"pip install pyosys-*.whl" \
|
||||
"\`\`\`" \
|
||||
> release_notes.md
|
||||
|
||||
- name: Create permanent release
|
||||
run: |
|
||||
TAG="build-${{ steps.meta.outputs.date }}-${{ steps.meta.outputs.short_sha }}"
|
||||
gh release create "$TAG" \
|
||||
all-wheels/*.whl \
|
||||
--target "${{ github.sha }}" \
|
||||
--title "Build ${{ steps.meta.outputs.date }} (${{ steps.meta.outputs.short_sha }})" \
|
||||
--notes-file release_notes.md
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Update latest release
|
||||
run: |
|
||||
git tag -f latest HEAD
|
||||
git push -f origin latest
|
||||
gh release delete latest --yes 2>/dev/null || true
|
||||
gh release create latest \
|
||||
all-wheels/*.whl \
|
||||
--target "${{ github.sha }}" \
|
||||
--title "Latest Build (${{ steps.meta.outputs.date }})" \
|
||||
--notes-file release_notes.md \
|
||||
--prerelease
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
|
@ -116,7 +116,7 @@ jobs:
|
|||
uses: ./.github/actions/setup-build-env
|
||||
with:
|
||||
runs-on: ${{ matrix.os }}
|
||||
get-test-deps: true
|
||||
get-build-deps: true
|
||||
get-iverilog: true
|
||||
|
||||
- name: Download build artifact
|
||||
|
|
|
|||
1
Makefile
1
Makefile
|
|
@ -29,7 +29,6 @@ ENABLE_LIBYOSYS_STATIC := 0
|
|||
ENABLE_ZLIB := 1
|
||||
ENABLE_HELP_SOURCE := 0
|
||||
ENABLE_BACKTRACE := 1
|
||||
VERIFIC_LINEFILE_INCLUDES_LOOPS := 1
|
||||
|
||||
# python wrappers
|
||||
ENABLE_PYOSYS := 1
|
||||
|
|
|
|||
|
|
@ -3151,7 +3151,7 @@ void RTLIL::Module::swap_names(RTLIL::Cell *c1, RTLIL::Cell *c2)
|
|||
|
||||
RTLIL::IdString RTLIL::Module::uniquify(RTLIL::IdString name)
|
||||
{
|
||||
int index = 0;
|
||||
int &index = uniquify_cache_[name];
|
||||
return uniquify(name, index);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2168,6 +2168,7 @@ public:
|
|||
void swap_names(RTLIL::Wire *w1, RTLIL::Wire *w2);
|
||||
void swap_names(RTLIL::Cell *c1, RTLIL::Cell *c2);
|
||||
|
||||
dict<RTLIL::IdString, int> uniquify_cache_;
|
||||
RTLIL::IdString uniquify(RTLIL::IdString name);
|
||||
RTLIL::IdString uniquify(RTLIL::IdString name, int &index);
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ OBJS += passes/silimate/reg_rename.o
|
|||
OBJS += passes/silimate/splitfanout.o
|
||||
OBJS += passes/silimate/splitlarge.o
|
||||
OBJS += passes/silimate/splitnetlist.o
|
||||
OBJS += passes/silimate/opt_timing_balance.o
|
||||
|
||||
OBJS += passes/silimate/opt_expand.o
|
||||
GENFILES += passes/silimate/peepopt_expand.h
|
||||
|
|
|
|||
|
|
@ -81,33 +81,47 @@ struct NegoptPass : public Pass {
|
|||
run_post = true;
|
||||
}
|
||||
|
||||
constexpr int max_iterations = 100;
|
||||
|
||||
for (auto module : design->selected_modules()) {
|
||||
if (run_pre) {
|
||||
did_something = true;
|
||||
while (did_something) {
|
||||
for (int iter = 0; iter < max_iterations && did_something; iter++) {
|
||||
did_something = false;
|
||||
peepopt_pm pm(module);
|
||||
pm.setup(module->selected_cells());
|
||||
|
||||
pm.run_manual2sub(); // Reduce manual 2's complement to subtraction first
|
||||
log_flush();
|
||||
pm.run_sub2neg();
|
||||
log_flush();
|
||||
pm.run_negexpand();
|
||||
log_flush();
|
||||
pm.run_negneg();
|
||||
log_flush();
|
||||
pm.run_negmux();
|
||||
log_flush();
|
||||
}
|
||||
if (did_something)
|
||||
log_warning("NEGOPT pre reached max iterations (%d) in module %s without convergence.\n", max_iterations, log_id(module));
|
||||
}
|
||||
|
||||
if (run_post) {
|
||||
did_something = true;
|
||||
while (did_something) {
|
||||
for (int iter = 0; iter < max_iterations && did_something; iter++) {
|
||||
did_something = false;
|
||||
peepopt_pm pm(module);
|
||||
pm.setup(module->selected_cells());
|
||||
|
||||
pm.run_negrebuild();
|
||||
log_flush();
|
||||
pm.run_muxneg();
|
||||
log_flush();
|
||||
pm.run_neg2sub();
|
||||
log_flush();
|
||||
}
|
||||
if (did_something)
|
||||
log_warning("NEGOPT post reached max iterations (%d) in module %s without convergence.\n", max_iterations, log_id(module));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -188,8 +188,11 @@ struct AbcProcess
|
|||
~AbcProcess() {
|
||||
if (pid == 0)
|
||||
return;
|
||||
if (to_child_pipe >= 0)
|
||||
if (to_child_pipe >= 0) {
|
||||
static const char quit_cmd[] = "quit\n";
|
||||
if (write(to_child_pipe, quit_cmd, sizeof(quit_cmd) - 1)) {}
|
||||
close(to_child_pipe);
|
||||
}
|
||||
int status;
|
||||
int ret = waitpid(pid, &status, 0);
|
||||
if (ret != pid) {
|
||||
|
|
|
|||
|
|
@ -72,16 +72,46 @@ struct AigmapPass : public Pass {
|
|||
dict<IdString, int> stat_not_replaced;
|
||||
int orig_num_cells = GetSize(module->cells());
|
||||
|
||||
dict<std::string, Aig> aig_cache;
|
||||
|
||||
pool<IdString> new_sel;
|
||||
for (auto cell : module->selected_cells())
|
||||
{
|
||||
Aig aig(cell);
|
||||
if (cell->type.in(ID($_AND_), ID($_NOT_))) {
|
||||
not_replaced_count++;
|
||||
stat_not_replaced[cell->type]++;
|
||||
if (select_mode)
|
||||
new_sel.insert(cell->name);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cell->type.in(ID($_AND_), ID($_NOT_)))
|
||||
aig.name.clear();
|
||||
if (nand_mode && cell->type == ID($_NAND_)) {
|
||||
not_replaced_count++;
|
||||
stat_not_replaced[cell->type]++;
|
||||
if (select_mode)
|
||||
new_sel.insert(cell->name);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (nand_mode && cell->type == ID($_NAND_))
|
||||
aig.name.clear();
|
||||
if (cell->type[0] != '$') {
|
||||
not_replaced_count++;
|
||||
stat_not_replaced[cell->type]++;
|
||||
if (select_mode)
|
||||
new_sel.insert(cell->name);
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string cache_key = cell->type.str();
|
||||
cell->parameters.sort();
|
||||
for (auto &p : cell->parameters)
|
||||
cache_key += stringf(":%s=%s", p.first.c_str(), p.second.as_string().c_str());
|
||||
|
||||
auto cache_it = aig_cache.find(cache_key);
|
||||
if (cache_it == aig_cache.end()) {
|
||||
auto r = aig_cache.insert(std::make_pair(cache_key, Aig(cell)));
|
||||
cache_it = r.first;
|
||||
}
|
||||
const Aig &aig = cache_it->second;
|
||||
|
||||
if (aig.name.empty()) {
|
||||
not_replaced_count++;
|
||||
|
|
@ -110,8 +140,8 @@ struct AigmapPass : public Pass {
|
|||
if (nand_mode && node.inverter) {
|
||||
bit = module->addWire(NEW_ID2_SUFFIX("bit"));
|
||||
auto gate = module->addNandGate(NEW_ID2_SUFFIX("nand"), A, B, bit);
|
||||
for (auto attr : cell->attributes)
|
||||
gate->attributes[attr.first] = attr.second;
|
||||
for (const auto &attr : cell->attributes)
|
||||
gate->attributes[attr.first] = attr.second;
|
||||
if (select_mode)
|
||||
new_sel.insert(gate->name);
|
||||
|
||||
|
|
@ -123,8 +153,8 @@ struct AigmapPass : public Pass {
|
|||
else {
|
||||
bit = module->addWire(NEW_ID2_SUFFIX("bit"));
|
||||
auto gate = module->addAndGate(NEW_ID2_SUFFIX("and"), A, B, bit);
|
||||
for (auto attr : cell->attributes)
|
||||
gate->attributes[attr.first] = attr.second;
|
||||
for (const auto &attr : cell->attributes)
|
||||
gate->attributes[attr.first] = attr.second;
|
||||
if (select_mode)
|
||||
new_sel.insert(gate->name);
|
||||
}
|
||||
|
|
@ -134,8 +164,8 @@ struct AigmapPass : public Pass {
|
|||
if (node.inverter) {
|
||||
SigBit new_bit = module->addWire(NEW_ID2_SUFFIX("new_bit"));
|
||||
auto gate = module->addNotGate(NEW_ID2_SUFFIX("inv"), bit, new_bit);
|
||||
for (auto attr : cell->attributes)
|
||||
gate->attributes[attr.first] = attr.second;
|
||||
for (const auto &attr : cell->attributes)
|
||||
gate->attributes[attr.first] = attr.second;
|
||||
bit = new_bit;
|
||||
if (select_mode)
|
||||
new_sel.insert(gate->name);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,511 @@
|
|||
#
|
||||
# opt_timing_balance regression coverage
|
||||
#
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Case: XOR chain with late leaf should be rewritten
|
||||
# ---------------------------------------------------------------------------
|
||||
log -header "opt_timing_balance: xor late leaf rewrite"
|
||||
log -push
|
||||
design -reset
|
||||
read_verilog <<EOF
|
||||
module top (
|
||||
input wire [7:0] u0,
|
||||
input wire [7:0] u1,
|
||||
input wire [15:0] a,
|
||||
input wire [15:0] b,
|
||||
input wire [15:0] c,
|
||||
input wire [15:0] d,
|
||||
output wire [15:0] y
|
||||
);
|
||||
wire [15:0] late = u0 * u1;
|
||||
assign y = late ^ a ^ b ^ c ^ d;
|
||||
endmodule
|
||||
EOF
|
||||
check -assert
|
||||
|
||||
equiv_opt -assert opt_timing_balance -logic
|
||||
design -load postopt
|
||||
select -assert-count 4 t:$xor
|
||||
select o:y %ci2 t:$xor %i -set root_xor
|
||||
select @root_xor i:late -assert-count 1
|
||||
|
||||
design -reset
|
||||
log -pop
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Case: Default mode should rewrite both logic and arithmetic cones
|
||||
# ---------------------------------------------------------------------------
|
||||
log -header "opt_timing_balance: default mode mixed categories"
|
||||
log -push
|
||||
design -reset
|
||||
read_verilog <<EOF
|
||||
module top (
|
||||
input wire [7:0] u0,
|
||||
input wire [7:0] u1,
|
||||
input wire [7:0] u2,
|
||||
input wire [7:0] u3,
|
||||
input wire [15:0] a,
|
||||
input wire [15:0] b,
|
||||
input wire [15:0] c,
|
||||
input wire [15:0] d,
|
||||
output wire [15:0] y_add,
|
||||
output wire [15:0] y_xor
|
||||
);
|
||||
wire [15:0] late_add = u0 * u1;
|
||||
wire [15:0] late_xor = u2 * u3;
|
||||
assign y_add = late_add + a + b + c + d;
|
||||
assign y_xor = late_xor ^ a ^ b ^ c ^ d;
|
||||
endmodule
|
||||
EOF
|
||||
check -assert
|
||||
|
||||
equiv_opt -assert opt_timing_balance
|
||||
design -load postopt
|
||||
select -assert-min 1 t:$add a:timing_balance_generated=1 %i
|
||||
select -assert-min 1 t:$xor a:timing_balance_generated=1 %i
|
||||
|
||||
design -reset
|
||||
log -pop
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Case: Running the pass twice should be idempotent on generated cones
|
||||
# ---------------------------------------------------------------------------
|
||||
log -header "opt_timing_balance: idempotent second invocation"
|
||||
log -push
|
||||
design -reset
|
||||
read_verilog <<EOF
|
||||
module top (
|
||||
input wire [7:0] u0,
|
||||
input wire [7:0] u1,
|
||||
input wire [15:0] a,
|
||||
input wire [15:0] b,
|
||||
input wire [15:0] c,
|
||||
input wire [15:0] d,
|
||||
output wire [15:0] y
|
||||
);
|
||||
wire [15:0] late = u0 * u1;
|
||||
assign y = late + a + b + c + d;
|
||||
endmodule
|
||||
EOF
|
||||
check -assert
|
||||
|
||||
opt_timing_balance -arith
|
||||
select -assert-count 4 t:$add a:timing_balance_generated=1 %i
|
||||
opt_timing_balance -arith
|
||||
select -assert-count 4 t:$add a:timing_balance_generated=1 %i
|
||||
|
||||
design -reset
|
||||
log -pop
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Case: Without negopt -pre, subtraction chains should not be rewritten
|
||||
# ---------------------------------------------------------------------------
|
||||
log -header "opt_timing_balance: direct subtraction conservative skip"
|
||||
log -push
|
||||
design -reset
|
||||
read_verilog <<EOF
|
||||
module top (
|
||||
input wire [7:0] a,
|
||||
input wire [7:0] b,
|
||||
input wire [7:0] c,
|
||||
input wire [7:0] d,
|
||||
output wire [7:0] y
|
||||
);
|
||||
assign y = a - b - c - d;
|
||||
endmodule
|
||||
EOF
|
||||
check -assert
|
||||
|
||||
equiv_opt -assert opt_timing_balance -arith
|
||||
design -load postopt
|
||||
select -assert-count 3 t:$sub
|
||||
select -assert-count 0 t:$add a:timing_balance_generated=1 %i
|
||||
|
||||
design -reset
|
||||
log -pop
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Case: Signed-width logic extension semantics are preserved under rewrite
|
||||
# ---------------------------------------------------------------------------
|
||||
log -header "opt_timing_balance: signed logic extension equivalence"
|
||||
log -push
|
||||
design -reset
|
||||
read_verilog <<EOF
|
||||
module top (
|
||||
input wire [7:0] u0,
|
||||
input wire [7:0] u1,
|
||||
input wire signed [1:0] a,
|
||||
input wire [3:0] b,
|
||||
input wire [3:0] c,
|
||||
output wire [3:0] y
|
||||
);
|
||||
wire [3:0] late = u0 * u1;
|
||||
assign y = late & a & b & c;
|
||||
endmodule
|
||||
EOF
|
||||
check -assert
|
||||
|
||||
equiv_opt -assert opt_timing_balance -logic
|
||||
design -load postopt
|
||||
select -assert-min 1 t:$and a:timing_balance_generated=1 %i
|
||||
select o:y %ci2 t:$and %i -set signed_logic_root
|
||||
select @signed_logic_root i:late -assert-count 1
|
||||
|
||||
design -reset
|
||||
log -pop
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Case: AND chain with late leaf should be rewritten
|
||||
# ---------------------------------------------------------------------------
|
||||
log -header "opt_timing_balance: and late leaf rewrite"
|
||||
log -push
|
||||
design -reset
|
||||
read_verilog <<EOF
|
||||
module top (
|
||||
input wire [7:0] u0,
|
||||
input wire [7:0] u1,
|
||||
input wire [15:0] a,
|
||||
input wire [15:0] b,
|
||||
input wire [15:0] c,
|
||||
input wire [15:0] d,
|
||||
output wire [15:0] y
|
||||
);
|
||||
wire [15:0] late = u0 * u1;
|
||||
assign y = late & a & b & c & d;
|
||||
endmodule
|
||||
EOF
|
||||
check -assert
|
||||
|
||||
equiv_opt -assert opt_timing_balance -logic
|
||||
design -load postopt
|
||||
select -assert-count 4 t:$and
|
||||
select o:y %ci2 t:$and %i -set root_and
|
||||
select @root_and i:late -assert-count 1
|
||||
|
||||
design -reset
|
||||
log -pop
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Case: OR chain with late leaf should be rewritten
|
||||
# ---------------------------------------------------------------------------
|
||||
log -header "opt_timing_balance: or late leaf rewrite"
|
||||
log -push
|
||||
design -reset
|
||||
read_verilog <<EOF
|
||||
module top (
|
||||
input wire [7:0] u0,
|
||||
input wire [7:0] u1,
|
||||
input wire [15:0] a,
|
||||
input wire [15:0] b,
|
||||
input wire [15:0] c,
|
||||
input wire [15:0] d,
|
||||
output wire [15:0] y
|
||||
);
|
||||
wire [15:0] late = u0 * u1;
|
||||
assign y = late | a | b | c | d;
|
||||
endmodule
|
||||
EOF
|
||||
check -assert
|
||||
|
||||
equiv_opt -assert opt_timing_balance -logic
|
||||
design -load postopt
|
||||
select -assert-count 4 t:$or
|
||||
select o:y %ci2 t:$or %i -set root_or
|
||||
select @root_or i:late -assert-count 1
|
||||
|
||||
design -reset
|
||||
log -pop
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Case: ADD chain with late leaf should be rewritten
|
||||
# ---------------------------------------------------------------------------
|
||||
log -header "opt_timing_balance: add late leaf rewrite"
|
||||
log -push
|
||||
design -reset
|
||||
read_verilog <<EOF
|
||||
module top (
|
||||
input wire [7:0] u0,
|
||||
input wire [7:0] u1,
|
||||
input wire [15:0] a,
|
||||
input wire [15:0] b,
|
||||
input wire [15:0] c,
|
||||
input wire [15:0] d,
|
||||
output wire [15:0] y
|
||||
);
|
||||
wire [15:0] late = u0 * u1;
|
||||
assign y = late + a + b + c + d;
|
||||
endmodule
|
||||
EOF
|
||||
check -assert
|
||||
|
||||
equiv_opt -assert opt_timing_balance -arith
|
||||
design -load postopt
|
||||
select -assert-count 4 t:$add
|
||||
select o:y %ci2 t:$add %i -set root_add
|
||||
select @root_add i:late -assert-count 1
|
||||
|
||||
design -reset
|
||||
log -pop
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Case: Balanced add tree should remain unchanged (no rewrite)
|
||||
# ---------------------------------------------------------------------------
|
||||
log -header "opt_timing_balance: balanced add no-op"
|
||||
log -push
|
||||
design -reset
|
||||
read_verilog <<EOF
|
||||
module top (
|
||||
input wire [15:0] a,
|
||||
input wire [15:0] b,
|
||||
input wire [15:0] c,
|
||||
input wire [15:0] d,
|
||||
input wire [15:0] e,
|
||||
input wire [15:0] f,
|
||||
input wire [15:0] g,
|
||||
input wire [15:0] h,
|
||||
output wire [15:0] y
|
||||
);
|
||||
assign y = ((a+b)+(c+d))+((e+f)+(g+h));
|
||||
endmodule
|
||||
EOF
|
||||
check -assert
|
||||
|
||||
equiv_opt -assert opt_timing_balance -arith
|
||||
design -load postopt
|
||||
select -assert-count 7 t:$add
|
||||
select -assert-count 0 t:$add a:timing_balance_generated=1 %i
|
||||
|
||||
design -reset
|
||||
log -pop
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Case: -logic mode must not rewrite arithmetic cones
|
||||
# ---------------------------------------------------------------------------
|
||||
log -header "opt_timing_balance: mode filter logic-only"
|
||||
log -push
|
||||
design -reset
|
||||
read_verilog <<EOF
|
||||
module top (
|
||||
input wire [7:0] u0,
|
||||
input wire [7:0] u1,
|
||||
input wire [15:0] a,
|
||||
input wire [15:0] b,
|
||||
input wire [15:0] c,
|
||||
input wire [15:0] d,
|
||||
output wire [15:0] y
|
||||
);
|
||||
wire [15:0] late = u0 * u1;
|
||||
assign y = late + a + b + c + d;
|
||||
endmodule
|
||||
EOF
|
||||
check -assert
|
||||
|
||||
equiv_opt -assert opt_timing_balance -logic
|
||||
design -load postopt
|
||||
select -assert-count 4 t:$add
|
||||
select -assert-count 0 t:$add a:timing_balance_generated=1 %i
|
||||
|
||||
design -reset
|
||||
log -pop
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Case: -arith mode must not rewrite logic cones
|
||||
# ---------------------------------------------------------------------------
|
||||
log -header "opt_timing_balance: mode filter arith-only"
|
||||
log -push
|
||||
design -reset
|
||||
read_verilog <<EOF
|
||||
module top (
|
||||
input wire [7:0] u0,
|
||||
input wire [7:0] u1,
|
||||
input wire [15:0] a,
|
||||
input wire [15:0] b,
|
||||
input wire [15:0] c,
|
||||
input wire [15:0] d,
|
||||
output wire [15:0] y
|
||||
);
|
||||
wire [15:0] late = u0 * u1;
|
||||
assign y = late ^ a ^ b ^ c ^ d;
|
||||
endmodule
|
||||
EOF
|
||||
check -assert
|
||||
|
||||
equiv_opt -assert opt_timing_balance -arith
|
||||
design -load postopt
|
||||
select -assert-count 4 t:$xor
|
||||
select -assert-count 0 t:$xor a:timing_balance_generated=1 %i
|
||||
|
||||
design -reset
|
||||
log -pop
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Case: Shared-fanout cone must preserve both tap and final output semantics
|
||||
# ---------------------------------------------------------------------------
|
||||
log -header "opt_timing_balance: shared fanout tap safety"
|
||||
log -push
|
||||
design -reset
|
||||
read_verilog <<EOF
|
||||
module top (
|
||||
input wire [15:0] a,
|
||||
input wire [15:0] b,
|
||||
input wire [15:0] c,
|
||||
input wire [15:0] d,
|
||||
output wire [15:0] tap,
|
||||
output wire [15:0] y
|
||||
);
|
||||
wire [15:0] x0 = a + b;
|
||||
wire [15:0] x1 = x0 + c;
|
||||
assign tap = x1;
|
||||
assign y = x1 + d;
|
||||
endmodule
|
||||
EOF
|
||||
check -assert
|
||||
|
||||
equiv_opt -assert opt_timing_balance -arith
|
||||
design -load postopt
|
||||
select o:tap %ci2 t:$add %i -assert-count 1
|
||||
select o:y %ci2 t:$add %i -assert-count 1
|
||||
|
||||
design -reset
|
||||
log -pop
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Case: Subtraction chain after negopt -pre should be balanced as add/neg
|
||||
# ---------------------------------------------------------------------------
|
||||
log -header "opt_timing_balance: negopt-pre normalized subtraction chain"
|
||||
log -push
|
||||
design -reset
|
||||
read_verilog <<EOF
|
||||
module top (
|
||||
input wire [7:0] a,
|
||||
input wire [7:0] b,
|
||||
input wire [7:0] c,
|
||||
input wire [7:0] d,
|
||||
output wire [7:0] y
|
||||
);
|
||||
assign y = a - b - c - d;
|
||||
endmodule
|
||||
EOF
|
||||
check -assert
|
||||
|
||||
negopt -pre
|
||||
select -assert-count 0 t:$sub
|
||||
equiv_opt -assert opt_timing_balance -arith
|
||||
design -load postopt
|
||||
select -assert-min 1 t:$add a:timing_balance_generated=1 %i
|
||||
|
||||
design -reset
|
||||
log -pop
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Case: Mixed-sign add chains should be skipped conservatively
|
||||
# ---------------------------------------------------------------------------
|
||||
log -header "opt_timing_balance: mixed-sign conservative skip"
|
||||
log -push
|
||||
design -reset
|
||||
read_verilog <<EOF
|
||||
module top (
|
||||
input wire signed [7:0] a,
|
||||
input wire [7:0] b,
|
||||
input wire [7:0] c,
|
||||
output wire [8:0] y
|
||||
);
|
||||
assign y = a + b + c;
|
||||
endmodule
|
||||
EOF
|
||||
check -assert
|
||||
|
||||
equiv_opt -assert opt_timing_balance -arith
|
||||
design -load postopt
|
||||
select -assert-count 2 t:$add
|
||||
select -assert-count 0 t:$add a:timing_balance_generated=1 %i
|
||||
|
||||
design -reset
|
||||
log -pop
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Case: Two independent arithmetic heads should both rewrite
|
||||
# ---------------------------------------------------------------------------
|
||||
log -header "opt_timing_balance: multi-head arithmetic rewrite"
|
||||
log -push
|
||||
design -reset
|
||||
read_verilog <<EOF
|
||||
module top (
|
||||
input wire [7:0] u0,
|
||||
input wire [7:0] u1,
|
||||
input wire [7:0] u2,
|
||||
input wire [7:0] u3,
|
||||
input wire [15:0] a,
|
||||
input wire [15:0] b,
|
||||
input wire [15:0] c,
|
||||
input wire [15:0] d,
|
||||
input wire [15:0] e,
|
||||
input wire [15:0] f,
|
||||
input wire [15:0] g,
|
||||
input wire [15:0] h,
|
||||
output wire [15:0] y0,
|
||||
output wire [15:0] y1
|
||||
);
|
||||
wire [15:0] late0 = u0 * u1;
|
||||
wire [15:0] late1 = u2 * u3;
|
||||
assign y0 = late0 + a + b + c + d;
|
||||
assign y1 = late1 + e + f + g + h;
|
||||
endmodule
|
||||
EOF
|
||||
check -assert
|
||||
|
||||
equiv_opt -assert opt_timing_balance -arith
|
||||
design -load postopt
|
||||
select -assert-min 2 t:$add
|
||||
select o:y0 %ci2 t:$add %i -set root0
|
||||
select o:y1 %ci2 t:$add %i -set root1
|
||||
select @root0 i:late0 -assert-count 1
|
||||
select @root1 i:late1 -assert-count 1
|
||||
|
||||
design -reset
|
||||
log -pop
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Case: Generated-cell tagging exists for rewritten cones (contract test)
|
||||
# ---------------------------------------------------------------------------
|
||||
log -header "opt_timing_balance: generated tag contract"
|
||||
log -push
|
||||
design -reset
|
||||
read_verilog <<EOF
|
||||
module top (
|
||||
input wire [7:0] u0,
|
||||
input wire [7:0] u1,
|
||||
input wire [15:0] a,
|
||||
input wire [15:0] b,
|
||||
input wire [15:0] c,
|
||||
input wire [15:0] d,
|
||||
output wire [15:0] y
|
||||
);
|
||||
wire [15:0] late = u0 * u1;
|
||||
assign y = late + a + b + c + d;
|
||||
endmodule
|
||||
EOF
|
||||
check -assert
|
||||
|
||||
equiv_opt -assert opt_timing_balance -arith
|
||||
design -load postopt
|
||||
select -assert-min 1 t:$add a:timing_balance_generated=1 %i
|
||||
|
||||
design -reset
|
||||
log -pop
|
||||
Loading…
Reference in New Issue