intel/systemc-compiler

subtraction and left side assignment

mzau opened this issue · 6 comments

mzau commented

having SystemC code

sc_in<uint16_t> a;
sc_in<uint16_t> b;
uint16_t result;
...
result = a.read() - b.read();

resulting in SystemVerilog code

logic [15:0] a;
logic [15:0] b;
logic [15:0] result;
...
result =  signed'({1'b0, a}) - signed'({1'b0, b})

Given (in my application) that b is always smaller than just a

result = a - b;

should work.
My issue is, that checking the code with verilator it will result in a warning

%Warning-WIDTH: Operator ASSIGN expects 16 bits on the Assign RHS, but Assign RHS's SUB generates 17 bits.

So my question is: Is the extension to 17 bit correct and required (in terms of the SV standards) ?

In the given code binary minus is signed which is applied to two signed arguments, so signed in generated SV is mandatory, see Clang AST below.
To avoid the signed cast you can use sc_uint<16> instead of uint16_t.

Clang AST for result = a.read() - b.read();:

BinaryOperator 0xaf0140 'uint16_t':'unsigned short' lvalue '='
|-DeclRefExpr 0xaefee0 'uint16_t':'unsigned short' lvalue Var 0xaefe60 'result' 'uint16_t':'unsigned short'
`-ImplicitCastExpr 0xaf0128 'uint16_t':'unsigned short' <IntegralCast>
  `-BinaryOperator 0xaf0108 'int' '-'
    |-ImplicitCastExpr 0xaf00c0 'int' <IntegralCast>
    | `-ImplicitCastExpr 0xaf00a8 'unsigned short':'unsigned short' <LValueToRValue>
    |   `-CXXMemberCallExpr 0xaeff88 'const unsigned short':'const unsigned short' lvalue
    |     `-MemberExpr 0xaeff58 '<bound member function type>' .read 0x7de568
    |       `-ImplicitCastExpr 0xaeffd8 'const class sc_core::sc_signal_t<unsigned short, sc_core::SC_ONE_WRITER>' lvalue <UncheckedDerivedToBase (sc_signal_t)>
    |         `-MemberExpr 0xaeff28 'sc_signal<uint16_t>':'class sc_core::sc_signal<unsigned short, sc_core::SC_ONE_WRITER>' lvalue ->sa 0x7e11a0
    |           `-CXXThisExpr 0xaeff18 'class A *' implicit this
    `-ImplicitCastExpr 0xaf00f0 'int' <IntegralCast>
      `-ImplicitCastExpr 0xaf00d8 'unsigned short':'unsigned short' <LValueToRValue>
        `-CXXMemberCallExpr 0xaf0068 'const unsigned short':'const unsigned short' lvalue
          `-MemberExpr 0xaf0038 '<bound member function type>' .read 0x7de568
            `-ImplicitCastExpr 0xaf0088 'const class sc_core::sc_signal_t<unsigned short, sc_core::SC_ONE_WRITER>' lvalue <UncheckedDerivedToBase (sc_signal_t)>
              `-MemberExpr 0xaf0008 'sc_signal<uint16_t>':'class sc_core::sc_signal<unsigned short, sc_core::SC_ONE_WRITER>' lvalue ->sb 0x7e12a0
                `-CXXThisExpr 0xaefff8 'class A *' implicit this

There will be a new tool option for fully unsigned design which suppresses all the signed in SV.

mzau commented

There will be a new tool option for fully unsigned design which suppresses all the signed in SV.
That'll be great. Thanks

Unsigned mode added in the last update, see https://github.com/intel/systemc-compiler/wiki/Tool-options-and-defines#unsigned-mode. This mode does check that all used types are unsigned. Unfortunately, I cannot remove signed' as there are cases when SC simulation uses signed operations for unsigned types (like minus for sc_biguint). So, signed' in generated SV required to keep the same semantic.

mzau commented

Thank you for the update. I did a complete build. I can add the UNSIGNED parameter to the svc_target for i.e. the counter_example and there is no error (as expected). But when I add UNSIGNED to a own project myproject_sctool returns

LLVM ERROR: CommonOptionsParser: failed to parse command-line arguments. [CommonOptionsParser]: sctool: Unknown command line argument '-check_unsigned'.  Try: 'sctool --help'
sctool: Did you mean '--help-hidden'?

but the test passes OK when I remove UNSIGNED

Please check if myproject_sctool linked with updated libScTool.so library with ldd command. Also, may be clear the build folder for this project and build it again helps.