3

I am porting from code from SystemVerilog to SystemC. SV is easily able to interpret packed structs of bits/logic as a single bit/logic vector. For example:

typedef struct logic {
  logic [31:0] blk1;  //63:32
  logic [4:0]  blk2;  //31:27
  logic [2:0]  blk3; //26:24
  logic [4:0]  blk4;  //23:19
  logic [2:0]  blk5;  //18:16
  logic [7:0]  blk6;  //15:8
  logic [7:0]  blk7;  //7:0
} typ_block;
...
typ_block blockA;
logic[63:0] blockB;
blockB = blockA; // no problem here

But with SystemC and using sc_lv<> template, this gives a compiler error due to the mismatching types.

struct typ_block {
  sc_lv<32> blk1;  //63:32
  sc_lv<5>  blk2;  //31:27
  sc_lv<3>  blk3; //26:24
  sc_lv<5>  blk4;  //23:19
  sc_lv<3>  blk5;  //18:16
  sc_lv<8>  blk6;  //15:8
  sc_lv<8>  blk7;  //7:0
};
...
typ_block blockA;
sc_lv<64> blockB;
blockB = blockA; // compiler error

Is there a good SystemC-supported way to do this equivalent? I can think of potential solutions but they are not elegant or concise, and I'm not sure if a c-style pointer cast would be safe/correct.

Rich
  • 1,165
  • 1
  • 15
  • 29

3 Answers3

4

Here is a slight improvement on your own answer. You don't need to convert to strings, as the sc_lv types can be concatenated with the () operator.

So you can simplify your function like this:

sc_lv<64> to64bit() { return (blk1, blk2, blk3, blk4, blk5, blk6, blk7); };

I imagine there is a way to make the simple assignment work by overloading some operator for typ_block, but I'm not sure what it is.

dwikle
  • 6,820
  • 1
  • 28
  • 38
  • dwikle, how is that return statement working? What is the name of the C++ construct to describe `(blk1, blk2, blk3[...])` ? – Ross Rogers Nov 17 '12 at 00:31
  • Ross, if I understand correctly this works because of the overloaded comma operator defined as concatenation for sc_lv and similar classes. See about halfway down on [this page](http://www.ht-lab.com/howto/vh2sc_tut/vh2sc_tut2.html). – Rich Jan 04 '13 at 19:41
1

This is using C++ typecast operator overloading to replace to64bit().

struct typ_block {
    sc_lv<32> blk1;  //63:32
    sc_lv<5>  blk2;  //31:27
    sc_lv<3>  blk3; //26:24
    sc_lv<5>  blk4;  //23:19
    sc_lv<3>  blk5;  //18:16
    sc_lv<8>  blk6;  //15:8
    sc_lv<8>  blk7;  //7:0

    operator sc_lv<64>() const {
        return sc_lv<64>((blk1.to_string() + blk2.to_string() + ...).c_str());
    }
};

typ_block blockA;
sc_lv<64> blockB;
blockB = blockA;

The restriction of this C++ operator is you must using the explicit expression to let compiler know the type conversion. It means you cannot use like blockB = (blockA).range(7,0);, you have to use blockB = sc_lv<64>(blockA).range(7,0);.

jclin
  • 2,449
  • 1
  • 21
  • 27
0

EDIT: I've combined these 3 answers to the following:

struct typ_block {
  sc_lv<32> blk1;  //63:32
  sc_lv<5>  blk2;  //31:27
  sc_lv<3>  blk3; //26:24
  sc_lv<5>  blk4;  //23:19
  sc_lv<3>  blk5;  //18:16
  sc_lv<8>  blk6;  //15:8
  sc_lv<8>  blk7;  //7:0

  // replacing the commented version by combining jclin's and dwinkle's answers
  // sc_lv<64> to64bit() { return (sc_lv<64>((blk1.to_string() + blk2.to_string() + blk3.to_string() + blk4.to_string() + blk5.to_string() + blk6.to_string() + blk7.to_string()).c_str())); };
  operator sc_lv<64>() const { return (blk1, blk2, blk3, blk4, blk5, blk6, blk7); };
};
...
typ_block blockA;
sc_lv<64> blockB;
blockB = blockA;
Rich
  • 1,165
  • 1
  • 15
  • 29