diff options
-rw-r--r-- | .travis.yml | 39 | ||||
-rwxr-xr-x | .travis/setup.sh | 2 | ||||
-rw-r--r-- | Dockerfile | 74 | ||||
-rw-r--r-- | passes/opt/opt_expr.cc | 50 | ||||
-rw-r--r-- | tests/various/opt_expr.ys | 205 |
5 files changed, 244 insertions, 126 deletions
diff --git a/.travis.yml b/.travis.yml index 4102f05fe..09f380831 100644 --- a/.travis.yml +++ b/.travis.yml @@ -40,35 +40,6 @@ matrix: env: - MATRIX_EVAL="CONFIG=gcc && CC=gcc-4.8 && CXX=g++-4.8" - # Latest gcc-6 on Travis Linux - - os: linux - addons: - apt: - sources: - - ubuntu-toolchain-r-test - packages: - - g++-6 - - gperf - - build-essential - - bison - - flex - - libreadline-dev - - gawk - - tcl-dev - - libffi-dev - - git - - graphviz - - xdot - - pkg-config - - python - - python3 - - libboost-system-dev - - libboost-python-dev - - libboost-filesystem-dev - - zlib1g-dev - env: - - MATRIX_EVAL="CONFIG=gcc && CC=gcc-6 && CXX=g++-6" - # Latest gcc supported on Travis Linux - os: linux addons: @@ -76,7 +47,7 @@ matrix: sources: - ubuntu-toolchain-r-test packages: - - g++-7 + - g++-9 - gperf - build-essential - bison @@ -96,7 +67,7 @@ matrix: - libboost-filesystem-dev - zlib1g-dev env: - - MATRIX_EVAL="CONFIG=gcc && CC=gcc-7 && CXX=g++-7" + - MATRIX_EVAL="CONFIG=gcc && CC=gcc-9 && CXX=g++-9" # Clang which ships on Trusty Linux - os: linux @@ -133,9 +104,9 @@ matrix: addons: apt: sources: - - llvm-toolchain-trusty-5.0 + - llvm-toolchain-xenial-8 packages: - - clang-5.0 + - clang-8 - gperf - build-essential - bison @@ -155,7 +126,7 @@ matrix: - libboost-filesystem-dev - zlib1g-dev env: - - MATRIX_EVAL="CONFIG=clang && CC=clang-5.0 && CXX=clang++-5.0" + - MATRIX_EVAL="CONFIG=clang && CC=clang-8 && CXX=clang++-8" # # Latest clang on Mac OS X # - os: osx diff --git a/.travis/setup.sh b/.travis/setup.sh index 4af0b8ee9..02879b974 100755 --- a/.travis/setup.sh +++ b/.travis/setup.sh @@ -51,7 +51,7 @@ fi git clone git://github.com/steveicarus/iverilog.git cd iverilog autoconf - ./configure --prefix=$HOME/.local-bin + CC=gcc CXX=g++ ./configure --prefix=$HOME/.local-bin make make install echo diff --git a/Dockerfile b/Dockerfile index 3c7188d82..549c73c97 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,33 +1,57 @@ -FROM ubuntu:18.04 as builder -LABEL author="Abdelrahman Hosny <abdelrahman.hosny@hotmail.com>" -ENV DEBIAN_FRONTEND=noninteractive -RUN apt-get update && apt-get install -y build-essential \ +ARG IMAGE="python:3-slim-buster" + +#--- + +FROM $IMAGE AS base + +RUN apt-get update -qq \ + && DEBIAN_FRONTEND=noninteractive apt-get -y install --no-install-recommends \ + ca-certificates \ clang \ + curl \ + libffi-dev \ + libreadline-dev \ + tcl-dev \ + graphviz \ + xdot \ + && apt-get autoclean && apt-get clean && apt-get -y autoremove \ + && update-ca-certificates \ + && rm -rf /var/lib/apt/lists + +#--- + +FROM base AS build + +RUN apt-get update -qq \ + && DEBIAN_FRONTEND=noninteractive apt-get -y install --no-install-recommends \ bison \ flex \ - libreadline-dev \ gawk \ - tcl-dev \ - libffi-dev \ + gcc \ git \ + iverilog \ pkg-config \ - python3 && \ - rm -rf /var/lib/apt/lists -COPY . / -RUN make && \ - make install - -FROM ubuntu:18.04 -ENV DEBIAN_FRONTEND=noninteractive -RUN apt-get update && apt-get install -y libreadline-dev tcl-dev - -COPY --from=builder /yosys /build/yosys -COPY --from=builder /yosys-abc /build/yosys-abc -COPY --from=builder /yosys-config /build/yosys-config -COPY --from=builder /yosys-filterlib /build/yosys-filterlib -COPY --from=builder /yosys-smtbmc /build/yosys-smtbmc - -ENV PATH /build:$PATH + && apt-get autoclean && apt-get clean && apt-get -y autoremove \ + && rm -rf /var/lib/apt/lists + +COPY . /yosys + +ENV PREFIX /opt/yosys + +RUN cd /yosys \ + && make \ + && make install \ + && make test + +#--- + +FROM base + +COPY --from=build /opt/yosys /opt/yosys + +ENV PATH /opt/yosys/bin:$PATH + RUN useradd -m yosys USER yosys -ENTRYPOINT ["yosys"] + +CMD ["yosys"] diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc index 8f6e660a2..fcdc1d173 100644 --- a/passes/opt/opt_expr.cc +++ b/passes/opt/opt_expr.cc @@ -641,7 +641,8 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons } } - if (cell->type.in(ID($add), ID($sub))) { + if (cell->type.in(ID($add), ID($sub))) + { RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID(A))); RTLIL::SigSpec sig_b = assign_map(cell->getPort(ID(B))); RTLIL::SigSpec sig_y = cell->getPort(ID(Y)); @@ -665,6 +666,53 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons did_something = true; } } + + if (cell->type == "$alu") + { + RTLIL::SigSpec sig_a = assign_map(cell->getPort("\\A")); + RTLIL::SigSpec sig_b = assign_map(cell->getPort("\\B")); + RTLIL::SigBit sig_ci = assign_map(cell->getPort("\\CI")); + RTLIL::SigBit sig_bi = assign_map(cell->getPort("\\BI")); + RTLIL::SigSpec sig_x = cell->getPort("\\X"); + RTLIL::SigSpec sig_y = cell->getPort("\\Y"); + RTLIL::SigSpec sig_co = cell->getPort("\\CO"); + + if (sig_ci.wire || sig_bi.wire) + goto next_cell; + + bool sub = (sig_ci == State::S1 && sig_bi == State::S1); + + // If not a subtraction, yet there is a carry or B is inverted + // then no optimisation is possible as carry will not be constant + if (!sub && (sig_ci != State::S0 || sig_bi != State::S0)) + goto next_cell; + + int i; + for (i = 0; i < GetSize(sig_y); i++) { + if (sig_b.at(i, State::Sx) == State::S0 && sig_a.at(i, State::Sx) != State::Sx) { + module->connect(sig_x[i], sub ? module->Not(NEW_ID, sig_a[i]).as_bit() : sig_a[i]); + module->connect(sig_y[i], sig_a[i]); + module->connect(sig_co[i], sub ? State::S1 : State::S0); + } + else if (!sub && sig_a.at(i, State::Sx) == State::S0 && sig_b.at(i, State::Sx) != State::Sx) { + module->connect(sig_x[i], sig_b[i]); + module->connect(sig_y[i], sig_b[i]); + module->connect(sig_co[i], State::S0); + } + else + break; + } + if (i > 0) { + cover("opt.opt_expr.fine.$alu"); + cell->setPort("\\A", sig_a.extract_end(i)); + cell->setPort("\\B", sig_b.extract_end(i)); + cell->setPort("\\X", sig_x.extract_end(i)); + cell->setPort("\\Y", sig_y.extract_end(i)); + cell->setPort("\\CO", sig_co.extract_end(i)); + cell->fixup_parameters(); + did_something = true; + } + } } if (cell->type.in(ID($reduce_xor), ID($reduce_xnor), ID($shift), ID($shiftx), ID($shl), ID($shr), ID($sshl), ID($sshr), diff --git a/tests/various/opt_expr.ys b/tests/various/opt_expr.ys index 0c61ac881..f0306efa1 100644 --- a/tests/various/opt_expr.ys +++ b/tests/various/opt_expr.ys @@ -5,144 +5,219 @@ module opt_expr_add_test(input [3:0] i, input [7:0] j, output [8:0] o); endmodule EOT -hierarchy -auto-top -proc -design -save gold +equiv_opt -assert opt_expr -fine +design -load postopt -opt_expr -fine -wreduce +select -assert-count 1 t:$add r:A_WIDTH=5 r:B_WIDTH=4 r:Y_WIDTH=5 %i %i %i -select -assert-count 1 t:$add r:A_WIDTH=4 r:B_WIDTH=4 r:Y_WIDTH=5 %i %i %i +########## -design -stash gate +# alumacc version of above +design -reset +read_verilog <<EOT +module opt_expr_add_test(input [3:0] i, input [7:0] j, output [8:0] o); + assign o = (i << 4) + j; +endmodule +EOT -design -import gold -as gold -design -import gate -as gate +alumacc +equiv_opt -assert opt_expr -fine +design -load postopt -miter -equiv -flatten -make_assert -make_outputs gold gate miter -sat -verify -prove-asserts -show-ports miter +select -assert-count 1 t:$alu r:A_WIDTH=4 r:B_WIDTH=5 r:Y_WIDTH=5 %i %i %i ########## +design -reset read_verilog <<EOT module opt_expr_add_signed_test(input signed [3:0] i, input signed [7:0] j, output signed [8:0] o); assign o = (i << 4) + j; endmodule EOT -hierarchy -auto-top -proc -design -save gold +equiv_opt -assert opt_expr -fine +design -load postopt -opt_expr -fine -wreduce +select -assert-count 1 t:$add r:A_WIDTH=5 r:B_WIDTH=4 r:Y_WIDTH=5 %i %i %i -select -assert-count 1 t:$add r:A_WIDTH=4 r:B_WIDTH=4 r:Y_WIDTH=5 %i %i %i +########## -design -stash gate +# alumacc version of above +design -reset +read_verilog <<EOT +module opt_expr_add_signed_test(input signed [3:0] i, input signed [7:0] j, output signed [8:0] o); + assign o = (i << 4) + j; +endmodule +EOT -design -import gold -as gold -design -import gate -as gate +alumacc +equiv_opt -assert opt_expr -fine +design -load postopt -miter -equiv -flatten -make_assert -make_outputs gold gate miter -sat -verify -prove-asserts -show-ports miter +select -assert-count 1 t:$alu r:A_WIDTH=4 r:B_WIDTH=5 r:Y_WIDTH=5 %i %i %i ########## +design -reset read_verilog <<EOT module opt_expr_sub_test1(input [3:0] i, input [7:0] j, output [8:0] o); assign o = j - (i << 4); endmodule EOT -hierarchy -auto-top -proc -design -save gold +equiv_opt -assert opt_expr -fine +design -load postopt -opt_expr -fine -wreduce +select -assert-count 1 t:$sub r:A_WIDTH=4 r:B_WIDTH=5 r:Y_WIDTH=5 %i %i %i -select -assert-count 1 t:$sub r:A_WIDTH=4 r:B_WIDTH=4 r:Y_WIDTH=5 %i %i %i +########## -design -stash gate +# alumacc version of above +design -reset +read_verilog <<EOT +module opt_expr_sub_test1(input [3:0] i, input [7:0] j, output [8:0] o); + assign o = j - (i << 4); +endmodule +EOT -design -import gold -as gold -design -import gate -as gate +alumacc +equiv_opt -assert opt_expr -fine +design -load postopt -miter -equiv -flatten -make_assert -make_outputs gold gate miter -sat -verify -prove-asserts -show-ports miter +dump +select -assert-count 1 t:$alu r:A_WIDTH=4 r:B_WIDTH=5 r:Y_WIDTH=5 %i %i %i ########## +design -reset read_verilog <<EOT module opt_expr_sub_signed_test1(input signed [3:0] i, input signed [7:0] j, output signed [8:0] o); assign o = j - (i << 4); endmodule EOT -hierarchy -auto-top -proc -design -save gold +equiv_opt -assert opt_expr -fine +design -load postopt -opt_expr -fine -wreduce +select -assert-count 1 t:$sub r:A_WIDTH=4 r:B_WIDTH=5 r:Y_WIDTH=5 %i %i %i -select -assert-count 1 t:$sub r:A_WIDTH=4 r:B_WIDTH=4 r:Y_WIDTH=5 %i %i %i +########## -design -stash gate +# alumacc version of above +design -reset +read_verilog <<EOT +module opt_expr_sub_signed_test1(input signed [3:0] i, input signed [7:0] j, output signed [8:0] o); + assign o = j - (i << 4); +endmodule +EOT -design -import gold -as gold -design -import gate -as gate +alumacc +equiv_opt -assert opt_expr -fine +design -load postopt -miter -equiv -flatten -make_assert -make_outputs gold gate miter -sat -verify -prove-asserts -show-ports miter +select -assert-count 1 t:$alu r:A_WIDTH=4 r:B_WIDTH=5 r:Y_WIDTH=5 %i %i %i ########## +design -reset read_verilog <<EOT module opt_expr_sub_test2(input [3:0] i, input [7:0] j, output [8:0] o); assign o = (i << 4) - j; endmodule EOT -hierarchy -auto-top -proc -design -save gold +equiv_opt -assert opt_expr -fine +design -load postopt -opt_expr -fine -wreduce +select -assert-count 1 t:$sub r:A_WIDTH=9 r:B_WIDTH=8 r:Y_WIDTH=9 %i %i %i -select -assert-count 1 t:$sub r:A_WIDTH=8 r:B_WIDTH=8 r:Y_WIDTH=9 %i %i %i +########## -design -stash gate +# alumacc version of above +design -reset +read_verilog <<EOT +module opt_expr_sub_test2(input [3:0] i, input [7:0] j, output [8:0] o); + assign o = (i << 4) - j; +endmodule +EOT -design -import gold -as gold -design -import gate -as gate +alumacc +opt_expr -fine +equiv_opt -assert opt_expr -fine +design -load postopt -miter -equiv -flatten -make_assert -make_outputs gold gate miter -sat -verify -prove-asserts -show-ports miter +select -assert-count 1 t:$alu r:A_WIDTH=9 r:B_WIDTH=8 r:Y_WIDTH=9 %i %i %i ########## +design -reset read_verilog <<EOT module opt_expr_sub_test4(input [3:0] i, output [8:0] o); assign o = 5'b00010 - i; endmodule EOT -hierarchy -auto-top -proc -design -save gold - -opt_expr -fine wreduce +equiv_opt -assert opt_expr -fine +design -load postopt select -assert-count 1 t:$sub r:A_WIDTH=2 r:B_WIDTH=4 r:Y_WIDTH=5 %i %i %i -design -stash gate +########## + +# alumacc version of above +design -reset +read_verilog <<EOT +module opt_expr_sub_test4(input [3:0] i, output [8:0] o); + assign o = 5'b00010 - i; +endmodule +EOT -design -import gold -as gold -design -import gate -as gate +wreduce +alumacc +equiv_opt -assert opt_expr -fine +design -load postopt + +select -assert-count 1 t:$alu r:A_WIDTH=2 r:B_WIDTH=4 r:Y_WIDTH=5 %i %i %i + +########### + +design -reset +read_verilog -icells <<EOT +module opt_expr_alu_test_ci0_bi0(input [7:0] a, input [3:0] b, output [8:0] x, y, co); + \$alu #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(8), .B_WIDTH(8), .Y_WIDTH(9)) alu (.A(a), .B({b, 4'b0000}), .CI(1'b0), .BI(1'b0), .X(x), .Y(y), .CO(co)); +endmodule +EOT +check + +equiv_opt -assert opt_expr -fine +design -load postopt +select -assert-count 1 t:$alu r:A_WIDTH=4 r:B_WIDTH=4 r:Y_WIDTH=5 %i %i %i + +########### + +design -reset +read_verilog -icells <<EOT +module opt_expr_alu_test_ci1_bi1(input [7:0] a, input [3:0] b, output [8:0] x, y, co); + \$alu #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(8), .B_WIDTH(8), .Y_WIDTH(9)) alu (.A(a), .B({b, 4'b0000}), .CI(1'b1), .BI(1'b1), .X(x), .Y(y), .CO(co)); +endmodule +EOT +check + +equiv_opt opt_expr -fine +design -load postopt +select -assert-count 1 t:$alu r:A_WIDTH=4 r:B_WIDTH=4 r:Y_WIDTH=5 %i %i %i + +########### + +design -reset +read_verilog -icells <<EOT +module opt_expr_alu_test_ci0_bi1(input [7:0] a, input [3:0] b, output [8:0] x, y, co); + \$alu #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(8), .B_WIDTH(8), .Y_WIDTH(9)) alu (.A(a), .B({b, 4'b0000}), .CI(1'b0), .BI(1'b1), .X(x), .Y(y), .CO(co)); +endmodule +EOT +check -miter -equiv -flatten -make_assert -make_outputs gold gate miter -sat -verify -prove-asserts -show-ports miter +equiv_opt opt_expr -fine +design -load postopt +select -assert-count 1 t:$alu r:A_WIDTH=8 r:B_WIDTH=8 r:Y_WIDTH=9 %i %i %i |