Catapult C simulation mismatch
The following bug was found in Catapult C 2020.
1. Description of bug
The following code produces the wrong result when compiled with Catapult C 2020.
This is just a modulo operation with a negative right-hand side number. The
expected result is 1
, however, Catapult C with the following example outputs
0xffffffff
(-1
if interpreted as signed).
./bug.cpp
#include <stdint.h> #pragma hls_design top uint32_t result() { int32_t a = -7; return 1 % a; }
The above might be a compiler specific behaviour, however, when the following is
passed to Catapult C, which just inlines the value of a
into the operation,
Catapult C agrees with GCC and outputs 1
.
#include <stdint.h> #pragma hls_design top uint32_t result() { return 1 % (-7); }
When looking at the hardware, no modulo operation is actually performed, meaning
this is just an analysis issue with Catapult C which computes the constant value
that should be returned. In the first case, Catapult C incorrectly generates a
constant that is always returned which contains 0xffffffff
:
ccs_out_v1 #(.rscid(32'sd1), .width(32'sd32)) return_rsci ( .idat(32'b11111111111111111111111111111111), .dat(return_rsc_dat) );
Whereas in the second case it generates a constant with the right value:
ccs_out_v1 #(.rscid(32'sd1), .width(32'sd32)) return_rsci ( .idat(32'b00000000000000000000000000000001), .dat(return_rsc_dat) );
2. Reproduction
The following files are necessary to reproduce the bug, using GCC
as the
reference compiler.
bug.tcl
go new solution file add ./bug.cpp go analyze go compile solution library add mgc_Xilinx-VIRTEX-7-2_beh -- -rtlsyntool Vivado -manufacturer Xilinx -family VIRTEX-7 -speed -2 -part xc7vx485tffg1157-2 solution library add Xilinx_RAMS solution library add Xilinx_ROMS solution library add Xilinx_FIFO go libraries directive set -CLOCKS {clk {-CLOCK_PERIOD 10 -CLOCK_EDGE rising -CLOCK_HIGH_TIME 5 -CLOCK_OFFSET 0.000000 -CLOCK_UNCERTAINTY 0.0 -RESET_KIND sync -RESET_SYNC_NAME rst -RESET_SYNC_ACTIVE high -RESET_ASYNC_NAME arst_n -RESET_ASYNC_ACTIVE low -ENABLE_NAME {} -ENABLE_ACTIVE high}} directive set -SCHED_USE_MULTICYCLE true go assembly go allocate go extract
main.cpp
#include "bug.cpp" #include <cstdio> int main() { uint32_t crc = result(); printf ("checksum = %08x\n", crc); }
run_bug.sh
gcc main.cpp -o test_gcc && ./test_gcc >out.gold.txt rm -rf Catapult >/dev/null 2>&1 catapult -shell -file run.tcl >/dev/null cp Catapult/result.v1/concat_sim_rtl.v result.v iverilog -o out.ver result.v tb.v ./out.ver | head -n1 >out.sim.txt diff out.gold.txt out.sim.txt
1c1 < checksum = 00000001 --- > checksum = ffffffff
tb.v
module testbench(); reg rst, clk; wire [31:0] return; wire rdy; result result_dat(clk, rst, return, rdy); initial begin rst = 1; clk = 0; #10 rst = 0; end always #5 clk = ~clk; always @(posedge clk) begin if (rdy) begin $display("checksum = %08h", return); $finish(); end end endmodule