TAGS :Viewed: 6 - Published at: a few seconds ago

[ Formatting Dynamic Array of Bits as String in SystemVerilog ]

How can I format a dynamic array of bits (or more correctly, logics) as a string, e.g., for UVM's convert2string? For example, I would like to convert

logic        vdyn[];  
vdyn = new [16] ('{0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1});  

to the string 0097.

I thought the following would work (the # are just to delimit the string for readability):

  fmt = $sformatf("#%%%0dh#", (vdyn.size-1)/4 + 1); // "#%4h#"
  vstr = $sformatf(fmt, { >> {vdyn}});

but it returns # x#, at least in Questa 10.3d (I suspect this is a bug - I'd be interested if it works on other simulators).

I tried converting it to a packed array first, but that runs into other problems. Without a size constraint on the result, the source value always gets left-justified in the destination variable, e.g.:

logic [63:0] v64;
v64 = {>> {vdyn}}; // 64'h0097000000000000

There's no way to print out just the part I want without using variable-size slices. The following works, but it requires that I know the size of the array at compile time:

v64 = 16'({>> {vdyn}});  // 64'h0000000000000097

The best thing I've found is the following "double-reverse" (note that I'm using << here, not >>):

     v64 = {&lt;&lt; {vdyn}};    // 64'he900000000000000 
     v64 = {&lt;&lt; {v64}};     // 64'h0000000000000097
     vstr = $sformatf(fmt, v64); // #0097#

It seems kind of hokey to have to do this, though. By the way, combining the first two statements into one doesn't work:

     v64 = {&lt;&lt; {{&lt;&lt; {vdyn}}}};     // 64'hZ900000000000000

(v64[63] is z for some reason). Again, I suspect this is a bug in Questa 10.3d.

Answer 1

Try casting a slice of the array and loop through. For example an 4 entry slice that is cast to a 4-bits value. A slize can be done with the -: or +: operator (See IEEE Std 1800-2012 § 7.4.3 Operations on arrays and § 7.4.6 Indexing and slicing of arrays)

vstr = "";
for(int i=vdyn.size()-1; i>=0; i-=4) begin
  vstr = $sformatf("%h%s", 4'({>>{vdyn[i -: 4]}}), vstr);
vstr = $sformatf("#%s#", vstr); // user formatting

The 4s in the code can be changed to something else depending how much leading 0 or a non-power-of-two formatting is desired, but it must be a numeric constant

I tried your code on some other simulators. vstr = $sformatf(fmt, { >> {vdyn}}); sometimes gave me compiling errors. Casting the array to something bigger than its expected max size seems to work

fmt = $sformatf("#%%%0dh#", (vdyn.size-1)/4 + 1); // "#%4h#"
vstr = $sformatf(fmt, 128'({ >> {vdyn}})); // works iff 128>=vdyn.size

Answer 2

I think the problem may be that the width of the streaming operator using dynamic types is not defined in a self-determined context (e.g. an argument to a system task). I think the LRM should have treated this an error.

A work-around is to shift the left-justified result to the right by

v64 = {>> {vdyn}}; 
v64 >>= 64-vdyn.size;