sv2v
sv2v copied to clipboard
Mutidimensional Packed Arrays Handler Does Not Match Commercial Synthesis Tools
Hello!
When sv2v processes multidimensional arrays, the output differs compared to passing the SystemVerilog directly to commercial tools.
Original SystemVerilog
logic [1:0][1:0] mem [2][2];
Original SystemVerilog passed into sv2v
reg [3:0] mem [0:1][0:1];
Original SystemVerilog passed into Genus
wire [1:0] \mem[1][1][0] ;
wire [1:0] \mem[0][1][0] ;
wire [1:0] \mem[0][0][1] ;
wire [1:0] \mem[1][0][0] ;
wire [1:0] \mem[1][0][1] ;
wire [1:0] \mem[0][0][0] ;
wire [1:0] \mem[1][1][1] ;
wire [1:0] \mem[0][1][1] ;
Issues
- sv2v causes synthesis to no longer match commercial tool behavior.
- sv2v puts faith in the synthesis tool optimizers to efficiently handle multiplications of array indices, i.e.
mem[2*i+:2]
.
Bigger Example
(Source code for provided examples: sv2v_array_example.tar.gz).
This is a summary of how sv2v, Genus, Vivado, and DC handle multidimensional arrays:
logic [1:0] mem;
sv2v
reg [1:0] mem;
Genus
wire [1:0] mem;
Vivado
wire \mem[0]_i_1_n_0 ;
wire \mem[1]_i_1_n_0 ;
DC
wire \mem\[1\] , \mem\[0\];
logic [1:0][1:0] mem;
sv2v
reg [3:0] mem;
Genus
wire [1:0] \mem[1] ;
wire [1:0] \mem[0] ;
Vivado
wire \mem[0][0]_i_1_n_0 ;
wire \mem[0][1]_i_1_n_0 ;
wire \mem[1][0]_i_1_n_0 ;
wire \mem[1][1]_i_1_n_0 ;
DC
wire \mem\[1\]\[1\] ,
\mem\[1\]\[0\] ,
\mem\[0\]\[1\] ,
\mem\[0\]\[0\];
logic [1:0] mem [2];
sv2v
reg [1:0] mem [0:1];
Genus
wire [1:0] \mem[1] ;
wire [1:0] \mem[0] ;
Vivado
wire \mem[0][0]_i_1_n_0 ;
wire \mem[0][1]_i_1_n_0 ;
wire \mem[1][0]_i_1_n_0 ;
wire \mem[1][1]_i_1_n_0 ;
DC
wire \mem\[0\]\[1\] ,
\mem\[0\]\[0\] ,
\mem\[1\]\[1\] ,
\mem\[1\]\[0\];
logic [1:0][1:0] mem [2];
sv2v
reg [3:0] mem [0:1];
Genus
wire [1:0] \mem[0][0] ;
wire [1:0] \mem[0][1] ;
wire [1:0] \mem[1][0] ;
wire [1:0] \mem[1][1] ;
Vivado
wire \mem[0][0][0]_i_1_n_0 ;
wire \mem[0][0][1]_i_1_n_0 ;
wire \mem[0][1][0]_i_1_n_0 ;
wire \mem[0][1][1]_i_1_n_0 ;
wire \mem[1][0][0]_i_1_n_0 ;
wire \mem[1][0][1]_i_1_n_0 ;
wire \mem[1][1][0]_i_1_n_0 ;
wire \mem[1][1][1]_i_1_n_0 ;
DC
wire \mem\[0\]\[1\]\[1\] ,
\mem\[0\]\[1\]\[0\] ,
\mem\[0\]\[0\]\[1\] ,
\mem\[0\]\[0\]\[0\] ,
\mem\[1\]\[1\]\[1\] ,
\mem\[1\]\[1\]\[0\] ,
\mem\[1\]\[0\]\[1\] ,
\mem\[1\]\[0\]\[0\];
logic [1:0] mem [2][2];
sv2v
reg [1:0] mem [0:1][0:1];
Genus
wire [1:0] \mem[0][0] ;
wire [1:0] \mem[0][1] ;
wire [1:0] \mem[1][0] ;
wire [1:0] \mem[1][1] ;
Vivado
wire \mem[0][0][0]_i_1_n_0 ;
wire \mem[0][0][1]_i_1_n_0 ;
wire \mem[0][1][0]_i_1_n_0 ;
wire \mem[0][1][1]_i_1_n_0 ;
wire \mem[1][0][0]_i_1_n_0 ;
wire \mem[1][0][1]_i_1_n_0 ;
wire \mem[1][1][0]_i_1_n_0 ;
wire \mem[1][1][1]_i_1_n_0 ;
DC
wire \mem\[0\]\[0\]\[1\] ,
\mem\[0\]\[0\]\[0\] ,
\mem\[0\]\[1\]\[1\] ,
\mem\[0\]\[1\]\[0\] ,
\mem\[1\]\[0\]\[1\] ,
\mem\[1\]\[0\]\[0\] ,
\mem\[1\]\[1\]\[1\] ,
\mem\[1\]\[1\]\[0\];
logic [1:0][1:0] mem [2][2];
sv2v
reg [3:0] mem [0:1][0:1];
Genus
wire [1:0] \mem[1][1][0] ;
wire [1:0] \mem[0][1][0] ;
wire [1:0] \mem[0][0][1] ;
wire [1:0] \mem[1][0][0] ;
wire [1:0] \mem[1][0][1] ;
wire [1:0] \mem[0][0][0] ;
wire [1:0] \mem[1][1][1] ;
wire [1:0] \mem[0][1][1] ;
Vivado
wire \mem[0][0][0][0]_i_1_n_0 ;
wire \mem[0][0][0][1]_i_1_n_0 ;
wire \mem[0][0][1][0]_i_1_n_0 ;
wire \mem[0][0][1][1]_i_1_n_0 ;
wire \mem[0][1][0][0]_i_1_n_0 ;
wire \mem[0][1][0][1]_i_1_n_0 ;
wire \mem[0][1][1][0]_i_1_n_0 ;
wire \mem[0][1][1][1]_i_1_n_0 ;
wire \mem[1][0][0][0]_i_1_n_0 ;
wire \mem[1][0][0][0]_i_2_n_0 ;
wire \mem[1][0][0][1]_i_1_n_0 ;
wire \mem[1][0][0][1]_i_2_n_0 ;
wire \mem[1][0][1][0]_i_1_n_0 ;
wire \mem[1][0][1][0]_i_2_n_0 ;
wire \mem[1][0][1][1]_i_1_n_0 ;
wire \mem[1][0][1][1]_i_2_n_0 ;
wire \mem[1][1][0][0]_i_1_n_0 ;
wire \mem[1][1][0][1]_i_1_n_0 ;
wire \mem[1][1][1][0]_i_1_n_0 ;
wire \mem[1][1][1][1]_i_1_n_0 ;
DC
wire \mem\[0\]\[0\]\[1\]\[1\] , \mem\[0\]\[0\]\[1\]\[0\] ,
\mem\[0\]\[0\]\[0\]\[1\] , \mem\[0\]\[0\]\[0\]\[0\] ,
\mem\[0\]\[1\]\[1\]\[1\] , \mem\[0\]\[1\]\[1\]\[0\] ,
\mem\[0\]\[1\]\[0\]\[1\] , \mem\[0\]\[1\]\[0\]\[0\] ,
\mem\[1\]\[0\]\[1\]\[1\] , \mem\[1\]\[0\]\[1\]\[0\] ,
\mem\[1\]\[0\]\[0\]\[1\] , \mem\[1\]\[0\]\[0\]\[0\] ,
\mem\[1\]\[1\]\[1\]\[1\] , \mem\[1\]\[1\]\[1\]\[0\] ,
\mem\[1\]\[1\]\[0\]\[1\] , \mem\[1\]\[1\]\[0\]\[0\];
Possible Solution
I wonder if it would make sense to convert all but 1 packed dimensions into unpacked dimensions:
Input
logic [1:0][1:0] mem [2][2];
Output
reg [1:0] mem [0:1][0:1][1:0];
One issue I see is that BRAM inference will change: the word size will be the 1st packed array dimension size, not the total size of the packed array. However, this may be fine because Vivado only supports BRAM inference on SystemVerilog with 1 packed array dimension (source), so this change will make sv2v more similar to Vivado. I haven't tested other tools.
Another possible issue is I'm not sure of tool support for mixing big-endian and little-endian unpacked arrays.
Thanks!