swapnilm Posted April 23, 2013 Report Share Posted April 23, 2013 Hello all, I am receiving serial bits in the monitor from DUT. This is RX path and independent from TX path i.e driver path. Then I have to make parallel data out of it using sipo(serial in parallel out) and then I have to decode the data to form the packet from the decoded bytes. In order to receive the all the bits of all the packets in RX path(monitor class), I have to give packet_length inside the for loop. Right now in order to check he functionality of monitor (in loop back mode), I am sending only one packet(8 bytes) so I know the number of bits, which I can use for packet_length parameter. But I want to make it generic because in real world I wont know how many packets might be coming. So the issue is, Is there any generic way in UVM to calculate the number of bytes(OR serial bits) coming into monitor? Is there any uvm method by which I can find this packet_length in a generic way? Packet structure is shown below: class transaction extends uvm_sequence_item; rand bit [7:0] sync; rand bit [7:0] sof; rand bit [15:0] header; rand bit [7:0] payload[]; rand bit [15:0] crc; rand bit [7:0] eof; constraint data_size_c { payload.size inside { [6 : 6]};}; ............. ............. endclass: transaction class monitor extends uvm_monitor; ..... virtual task run_phase(uvm_phase phase); transaction pkt; forever begin int pkt_len = 130; //This is in bits,HERE I NEED TO PASS THE CALCULATED LENGTH FROM SOME GENERIC UVM FUNCTION,TO START RECEIVING ALL THE SERIAL BITS. repeat(3)@(dut_vi.clock); for (int j = 0; j < pkt_len; j++) begin serialin = dut_vi.data; $display("san14- Display of the serial line serialin %b",serialin); $display("san15- Display of the Serial Line dut_vi.data %b",dut_vi.data); sipo(serialin); end void'(decode(bytes)); pkt = transaction::type_id::create("pkt1"); $display("SM447- Display of the bytes array received after decoding %h",decdrout2); void'(pkt.unpack_bytes(decdrout2)); uvm_report_info(get_full_name(),"Decoded completely 10bits into 8bits ...",UVM_LOW); uvm_report_info(get_full_name(),"Started unpacking of received bytes ...",UVM_LOW); pkt.print(); uvm_report_info(get_full_name(),"Completed unpacking of received bytes ...",UVM_LOW); Montr2Agnt_port.write(pkt); end uvm_report_info(get_full_name(),"Sending received packet from monitor to the Scoreboard ...",UVM_LOW); endtask: run_phase ........... .......... endclass: monitor Any help is appreciated, thanks Quote Link to comment Share on other sites More sharing options...
swapnilm Posted April 24, 2013 Author Report Share Posted April 24, 2013 Can anyone please give me some guidance on above issue? Thanks, Quote Link to comment Share on other sites More sharing options...
apfitch Posted April 24, 2013 Report Share Posted April 24, 2013 There's a system function $bits which returns the size of certain types in bits - but it's not supposed to be used on dynamic data types (see 1800-2012 20.6.2). But in your case, you know that there is 56 bits of fixed data plus 8 bits * the length of the packet, i.e. (pkt.payload.size) * 8 + 56 The neatest solution would be to add a length method to your transaction class. regards Alan Quote Link to comment Share on other sites More sharing options...
dave_59 Posted April 25, 2013 Report Share Posted April 25, 2013 There's a system function $bits which returns the size of certain types in bits - but it's not supposed to be used on dynamic data types (see 1800-2012 20.6.2). regards Alan There's a difference between a data type and a variable or expression of a certain data type. It's only the type (i.e. typedef) that is not allowed to be dynamic. You can use it on a dynamically sized variable, and in this case, a member of a class. Quote Link to comment Share on other sites More sharing options...
lrcrsr Posted April 25, 2013 Report Share Posted April 25, 2013 $bits(object) would work very well to give you the packet length. I dont believe there is any restriction on using dynamic types. In fact, you will find an example of $bits being used on an class object in page 242 of the recent LRM (1800-2012). Hope this helps! Loganath Quote Link to comment Share on other sites More sharing options...
apfitch Posted April 25, 2013 Report Share Posted April 25, 2013 Oops, thanks Dave for spotting my mistake. I mis-read this "It shall be an error to:— Use the $bits system function directly with a dynamically sized data type identifier." - but as Loganath says, there is indeed an example on p242, regards Alan Quote Link to comment Share on other sites More sharing options...
swapnilm Posted April 25, 2013 Author Report Share Posted April 25, 2013 Dear all, I appreciate the feedback from all of you. I used $bits in the unpack function in the transaction class as shown below in the code: class transaction extends uvm_sequence_item; rand bit [7:0] sync; rand bit [7:0] sof; rand bit [15:0] header; rand bit [7:0] payload[]; rand bit [15:0] crc; rand bit [7:0] eof; constraint data_size_c { payload.size inside { [6 : 6]};}; `uvm_object_utils_begin(transaction) `uvm_field_int(sync, UVM_ALL_ON|UVM_NOPACK) `uvm_field_int(sof, UVM_ALL_ON|UVM_NOPACK) `uvm_field_int(header, UVM_ALL_ON|UVM_NOPACK) `uvm_field_array_int(payload, UVM_ALL_ON|UVM_NOPACK) `uvm_field_int(crc, UVM_ALL_ON|UVM_NOPACK) `uvm_field_int(eof, UVM_ALL_ON|UVM_NOPACK) `uvm_object_utils_end function void do_pack(uvm_packer packer); int i; super.do_pack(packer); packer.pack_field_int(sync,$bits(sync)); packer.pack_field_int(sof,$bits(sof)); packer.pack_field_int(header,$bits(header)); foreach(payload[i]) packer.pack_field_int(payload[i],8); packer.pack_field_int(crc,$bits(crc)); packer.pack_field_int(eof,$bits(eof)); endfunction : do_pack function void do_unpack(uvm_packer packer); //The unpack methods extract property values from an array of bits,bytes or ints. int i; //The do_unpack method is the user-definable hook called by the unpack method. int unsigned packet_size_in_bytes, payload_size_in_bytes; super.do_unpack(packer); sync = packer.unpack_field_int($bits(sync)); sof = packer.unpack_field_int($bits(sof)); header = packer.unpack_field_int($bits(header)); packet_size_in_bytes = packer.get_packed_size() / $bits(byte); // get_packed_size returns the number of bits that were packed. payload_size_in_bytes = packet_size_in_bytes -(($bits(sync) + $bits(sof) + $bits(header) + $bits(crc) + $bits(eof)) / $bits(byte) ); $display("san999- Display of the packet size %h",packet_size_in_bytes); pkt_len = packet_size_in_bytes * 10; // CAN I PASS THIS VARIABLE pkt_len TO MONITOR CLASS AND GET IT'S VALUE EVEN BEFORE THE SERIAL BITS ARE ACTUALLY BEING RECEIVED? $display("san996- Display of the packet length in bits %h",pkt_len); payload = new [payload_size_in_bytes]; foreach (payload[i]) //`uvm_unpack_int(payload[i]) // payload = new[sz]; // for ( i=0; i<sz; i++) payload[i] = packer.unpack_field_int(8); //8 less than or equal to 64 bits $display("san995-tran- Display of the payload contents %h",payload.size()); $display("san998-tran- Display of the payload contents %h",payload_size_in_bytes); crc = packer.unpack_field_int($bits(crc)); eof = packer.unpack_field_int($bits(eof)); endfunction : do_unpack endclass:transaction class monitor extends uvm_monitor; ..... virtual task run_phase(uvm_phase phase); transaction pkt; forever begin int pkt_len = 130; //This is in bits,HERE I NEED TO PASS THE CALCULATED LENGTH FROM SOME GENERIC UVM FUNCTION,TO START RECEIVING ALL THE SERIAL BITS. repeat(3)@(dut_vi.clock); for (int j = 0; j < pkt_len; j++) begin serialin = dut_vi.data; $display("san14- Display of the serial line serialin %b",serialin); $display("san15- Display of the Serial Line dut_vi.data %b",dut_vi.data); sipo(serialin); end void'(decode(bytes)); pkt = transaction::type_id::create("pkt1"); $display("SM447- Display of the bytes array received after decoding %h",decdrout2); void'(pkt.unpack_bytes(decdrout2)); uvm_report_info(get_full_name(),"Decoded completely 10bits into 8bits ...",UVM_LOW); uvm_report_info(get_full_name(),"Started unpacking of received bytes ...",UVM_LOW); pkt.print(); uvm_report_info(get_full_name(),"Completed unpacking of received bytes ...",UVM_LOW); Montr2Agnt_port.write(pkt); end uvm_report_info(get_full_name(),"Sending received packet from monitor to the Scoreboard ...",UVM_LOW); endtask: run_phase ........... .......... endclass: monitor CAN I PASS THIS VARIABLE pkt_len TO MONITOR CLASS IN THAT FORLOOP AND GET IT'S VALUE EVEN BEFORE THE SERIAL BITS ARE ACTUALLY BEING RECEIVED? BECAUSE UNPACK FUNCTION WILL GET THE PACKET LENGTH AFTER DECODE FUNCTION. AND THE pkt_len VARIABLE COMES EARLY IN THE CODE. IF I CAN PASS, THEN HOW IS IT DONE? PLEASE GIVE SOME GUIDANCE ON THIS. I APPRECIATE YOUR HELP, THANKS Quote Link to comment Share on other sites More sharing options...
swapnilm Posted May 8, 2013 Author Report Share Posted May 8, 2013 hello all, Can I get to know the packet length from a Packing function(i.e. do_pack), like by using get_packed_size() method in do_pack function? So that I would know the packet length up in advance even before I receive that packet in monitor. Can this be done? please give some feedback, would appreciate it. Thanks, Quote Link to comment Share on other sites More sharing options...
mea1201 Posted May 8, 2013 Report Share Posted May 8, 2013 Can't you detect SOF and EOF from the serial input that you're monitoring? Wouldn't that be a more reliable way to collect your packets instead of knowing the packet length ahead of time, and drive a fixed loop with that? How can you know the packet length before you even start collecting the packet in the monitor? I don't get it. I would also add the pkt_len variable to the transaction class, and let do_unpack determine the length and save it to the variable in the transaction. That way, the length is always coupled with the packet it belongs to. Anyone else interested in a packet's length can do a simple query or get to obtain the value. I'm not sure it really makes much sense to store SOF and EOF in the transaction. I would imagine that whatever your serial bitstream is that the SOF and EOF are encoded, so you can set up a state machine in your monitor to detect the packet boundaries. Otherwise, I just don't understand how you can realistically determine where packets begin and end from a random stream of bits. Does any of this make sense? Or, have I completely misunderstood what you are trying to do? Quote Link to comment Share on other sites More sharing options...
swapnilm Posted May 10, 2013 Author Report Share Posted May 10, 2013 Hello mea1201, Yea, what you are saying makes sense. But I want to know that, in the end, the packets are travelling as an object to the monitor and I can get the packet length when I pack the packet bytes in do_pack function (in transaction class itself). So I know whats the length of the packet before even I send the packet to driver/ monitor. So in this way, I will have packet length for each and every packet beforehand, even before I send it across. So can this not be done, if I happen to pass the Variable in which I stored that packet length, through a package, to the monitor? This is my question? I hope whatever I am saying is understandable. Can this be done? Please throw some light. I appreciate your feedback. Quote Link to comment Share on other sites More sharing options...
jadec Posted May 23, 2013 Report Share Posted May 23, 2013 The answer to the question is a question "How does your hardware determine the packet length?" Once you know that, you can implement the same logic in your monitor. It will be either so interface signaling the start and end of packet. Or some common header format. If it's the latter, you'll need a base class for your packet that can decode the common header (both for the length and to determine the actual packet type). Quote Link to comment Share on other sites More sharing options...
wushan Posted June 1, 2013 Report Share Posted June 1, 2013 To swapnilm, I'm not sure to understand what you need. My suggestion is add a pkt_len member variable to the class transaction, and constrain the pkt_len {8..1000}, then constrain the payload.size() == pkt_len - 8. If you can get the item directly, you will get the length just by the varialbe pkt_len. If you need to get the item by the monitor, this variable pkt_len doesn't work, you need get the infomation by pack the transaction, or just count the cycle of the transaction. Best regards Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.