diff --git a/backends/functional/cxx.cc b/backends/functional/cxx.cc index a4153035dad..f0ceb5d76d4 100644 --- a/backends/functional/cxx.cc +++ b/backends/functional/cxx.cc @@ -190,6 +190,8 @@ class CxxComputeGraphFactory { T logical_shift_right(T a, T b, int y_width, int) { return graph.add(CxxFunction(ID($shr), y_width, {{ID(WIDTH), y_width}}), 0, std::array{a, b}); } T arithmetic_shift_right(T a, T b, int y_width, int) { return graph.add(CxxFunction(ID($asr), y_width, {{ID(WIDTH), y_width}}), 0, std::array{a, b}); } T mul(T a, T b, int width) { return graph.add(CxxFunction(ID($mul), width), 0, std::array{a, b}); } + T mod(T a, T b, int width) { return graph.add(CxxFunction(ID($mod), width), 0, std::array{a, b}); } + T div(T a, T b, int width) { return graph.add(CxxFunction(ID($div), width), 0, std::array{a, b}); } T constant(RTLIL::Const value) { return graph.add(CxxFunction(ID($$const), value.size(), {{ID(value), value}}), 0); diff --git a/backends/functional/cxx_runtime/sim.h b/backends/functional/cxx_runtime/sim.h index 0cbbe9831a1..e6e1c2f953a 100644 --- a/backends/functional/cxx_runtime/sim.h +++ b/backends/functional/cxx_runtime/sim.h @@ -379,4 +379,34 @@ Signal $mul(Signal const& a, Signal const& b) return ret; } +template +Signal $div(Signal const& a, Signal const& b) +{ + Signal quotient = $const(0); + Signal remainder = a; + Signal divisor = b; + + for(int i = n - 1; i >= 0; i--) { + if(as_int(remainder) >= (as_int(divisor) << i)) { + remainder = $sub(remainder, $shl(divisor, $const(i))); + quotient[i] = true; + } + } + return quotient; +} + +template +Signal $mod(Signal const& a, Signal const& b) +{ + Signal remainder = a; + Signal divisor = b; + + for(int i = n - 1; i >= 0; i--) { + if(as_int(remainder) >= (as_int(divisor) << i)) { + remainder = $sub(remainder, $shl(divisor, $const(i))); + } + } + return remainder; +} + #endif diff --git a/backends/functional/smtlib.cc b/backends/functional/smtlib.cc index 2811d0bea7e..30883577215 100644 --- a/backends/functional/smtlib.cc +++ b/backends/functional/smtlib.cc @@ -368,6 +368,8 @@ class SmtlibComputeGraphFactory { T logical_shift_right(T a, T b, int y_width, int b_width) { return shift("bvlshl", a, b, y_width, b_width); } T arithmetic_shift_right(T a, T b, int y_width, int b_width) { return shift("bvashr", a, b, y_width, b_width, true); } T mul(T a, T b, int width) { return node(SExpr {"bvmul", Arg(1), Arg(2)}, width, {a, b}); } + T div(T a, T b, int width) { return node(SExpr {"bvudiv", Arg(1), Arg(2)}, width, {a, b}); } + T mod(T a, T b, int width) { return node(SExpr {"bvurem", Arg(1), Arg(2)}, width, {a, b}); } T constant(RTLIL::Const value) { return node(SExpr(value), value.size(), {}); } T input(IdString name, int width) { diff --git a/kernel/graphtools.h b/kernel/graphtools.h index 1c6b927739d..907a2b1cf4a 100644 --- a/kernel/graphtools.h +++ b/kernel/graphtools.h @@ -189,6 +189,18 @@ class CellSimplifier { T a = extend(inputs.at(ID(A)), a_width, width, is_signed); T b = extend(inputs.at(ID(B)), b_width, width, is_signed); return extend(factory.mul(a, b, width), width, y_width, is_signed); + }else if(cellType == ID($div)){ + bool is_signed = a_signed && b_signed; + int width = max(a_width, b_width); + T a = extend(inputs.at(ID(A)), a_width, width, is_signed); + T b = extend(inputs.at(ID(B)), b_width, width, is_signed); + return extend(factory.div(a, b, width), width, y_width, is_signed); + }else if(cellType == ID($mod)){ + bool is_signed = a_signed && b_signed; + int width = max(a_width, b_width); + T a = extend(inputs.at(ID(A)), a_width, width, is_signed); + T b = extend(inputs.at(ID(B)), b_width, width, is_signed); + return extend(factory.mod(a, b, width), width, y_width, is_signed); }else{ log_error("unhandled cell in CellSimplifier %s\n", cellType.c_str()); } diff --git a/tests/functional/single_bit/run-test.sh b/tests/functional/single_bit/run-test.sh index d71a2c90fb8..7fe74cc47d4 100755 --- a/tests/functional/single_bit/run-test.sh +++ b/tests/functional/single_bit/run-test.sh @@ -24,7 +24,8 @@ run_test() { if ./vcd_harness ${base_name}_functional_cxx.vcd; then # Run yosys to process each Verilog file - if ${BASE_PATH}yosys -p "read_verilog $verilog_file; sim -r ${base_name}_functional_cxx.vcd -scope my_module -timescale 1us -sim-cmp"; then + if ${BASE_PATH}yosys -p "read_verilog $verilog_file; sim -r ${base_name}_functional_cxx.vcd -scope my_module -vcd ${base_name}_yosys_sim.vcd -timescale 1us -sim-cmp"; then + # ${BASE_PATH}yosys -p "read_verilog $verilog_file; sim -vcd ${base_name}_yosys_sim.vcd -r ${base_name}_functional_cxx.vcd -scope my_module -timescale 1us" echo "Yosys sim $verilog_file successfully." else echo "Yosys simulation of $verilog_file failed. There is a discrepancy with functional cxx"