1
\$\begingroup\$

In the following code, I force a random variable 'ResBlks' with a value (setting its rand_mode to 0), then attempt to randomize the transaction:

`include "uvm_macros.svh"

package mytest;
import uvm_pkg::*;

typedef enum logic {Type2=0, Sorted=1} PhyRBAlloc_t; // RBs allocation type

class Txn extends uvm_sequence_item;

  rand bit [6:0] ResBlks; // Number of resource blocks (NRB)
  rand PhyRBAlloc_t PhyRBAllocType; // Physical RB allocation type
  rand integer PhyRB[2][]; // Physical RB mapping

  // Array of unique values
  constraint ArrSize {
    PhyRB[0].size() > 0;
    PhyRB[0].size() <= ResBlks;
    PhyRB[1].size() == PhyRB[0].size();
  }
  constraint vals {
    foreach(PhyRB[0][i]) PhyRB[0][i] < ResBlks;
    if(PhyRBAllocType == Type2) {
      foreach(PhyRB[1][i]) PhyRB[1][i] < ResBlks;
    }
    unique { PhyRB[0] };
    unique { PhyRB[1] } ;
  }

  constraint ResBlksConstraint {
    ResBlks inside {6,15,25,50,75,100};
  }

  function void post_randomize;
    if(PhyRBAllocType == Sorted) begin
      PhyRB[0].sort();
      PhyRB[1] = PhyRB[0];
    end
  endfunction

  function new(string name="Txn");
    super.new(name);
  endfunction

  `uvm_object_utils_begin(Txn)
    `uvm_field_int(ResBlks, UVM_DEFAULT)
    `uvm_field_array_int(PhyRB[0], UVM_DEFAULT)
    `uvm_field_array_int(PhyRB[1], UVM_DEFAULT)
  `uvm_object_utils_end

endclass

class Seq extends uvm_sequence #(Txn);
  `uvm_object_utils(Seq)

  function new(string name="Seq");
    super.new(name);
  endfunction

  task body();

      req = Txn::type_id::create("req");
      start_item(req);

      req.ResBlks = 50;
      req.ResBlks.rand_mode(0);
      if(!req.randomize())
        `uvm_error("RAND", "txn rand failed")
      finish_item(req);
  endtask: body
endclass: Seq

typedef uvm_sequencer #(Txn) Sqr;

class Drv extends uvm_driver#(Txn);
  `uvm_component_utils(Drv)
  virtual MyIf vif;
  Txn txn;

  function new(string name="Drv", uvm_component parent=null);
    super.new(name, parent);
  endfunction

  function void build_phase(uvm_phase phase);
    if(!uvm_config_db #(virtual MyIf)::get(this, "", "vif", vif))
      `uvm_fatal("NO VIF", "No virtual interface");
  endfunction: build_phase

  task run_phase(uvm_phase phase);

    vif.nRst = 0;
    vif.Init = 0;
    #100 @(negedge vif.Clk);
    vif.nRst = 1;


    forever begin
      seq_item_port.get_next_item(txn);
      // drive txn

        @vif.cb
            vif.cb.ResBlks <= txn.ResBlks;
            vif.cb.Init <= 1;
        @vif.cb vif.cb.Init <= 0;

     @vif.cb GenRBAlloc;

      seq_item_port.item_done();
    end

  endtask: run_phase

  task GenRBAlloc;
    integer i;

    if(!txn.randomize(PhyRBAllocType))
      `uvm_error("RAND", "PhyRBAllocType rand failed")
    if(!txn.randomize(PhyRB))
      `uvm_error("RAND", "PhyRB rand failed")

    `uvm_info("SFRM", $sformatf("UsedRBNum: %0d", txn.PhyRB[0].size()), UVM_MEDIUM)
    `uvm_info("SFRM", $sformatf("RB allocation: %s", txn.PhyRBAllocType.name()), UVM_MEDIUM)
    `uvm_info("SFRM", $sformatf("PhyRB[0]: %0p", txn.PhyRB[0]), UVM_MEDIUM)
    `uvm_info("SFRM", $sformatf("PhyRB[1]: %0p", txn.PhyRB[1]), UVM_MEDIUM)

  endtask: GenRBAlloc

endclass: Drv

class Agent  extends uvm_agent;
  `uvm_component_utils(Agent)
  Sqr sqr;
  Drv drv;

  function new(string name="Agent", uvm_component parent=null);
    super.new(name, parent);
  endfunction

  function void build_phase(uvm_phase phase);
    if(get_is_active() == UVM_ACTIVE) begin
      sqr = Sqr::type_id::create("sqr", this);
      drv = Drv::type_id::create("drv", this);
    end
  endfunction: build_phase

  function void connect_phase(uvm_phase phase);
    if(get_is_active() == UVM_ACTIVE)
      drv.seq_item_port.connect(sqr.seq_item_export);
  endfunction: connect_phase

endclass: Agent

class Env  extends uvm_env;
  `uvm_component_utils(Env)
  Agent agent;

  function new(string name="Env", uvm_component parent=null);
    super.new(name, parent);
  endfunction

  function void build_phase(uvm_phase phase);
    agent = Agent::type_id::create("agent", this);
  endfunction: build_phase

endclass: Env

class ParamTest extends uvm_test;
  `uvm_component_utils(ParamTest)
  Env env;

  function new(string name="ParamTest", uvm_component parent=null);
    super.new(name, parent);
  endfunction

  function void build_phase(uvm_phase phase);
    env = Env::type_id::create("env", this);
  endfunction: build_phase

  task run_phase(uvm_phase phase);
    Seq seq;
    phase.raise_objection(this);
    seq = Seq::type_id::create("seq");
    seq.start(env.agent.sqr);
    phase.drop_objection(this);
  endtask: run_phase

endclass: ParamTest

endpackage

interface MyIf (
  // Clock & reset:
  input Clk
);

parameter CQ = 0;
// Inputs
logic nRst;
logic Init; // Re-initialize the block
logic [6:0] ResBlks; // Number of resource blocks (NRB)
logic [6:0] UsedRBNum;// Length of type 2 distributed bitmap.
logic [6:0] PhyRB0;// Type 2-Distributed physical RB mapping for even slots.
logic [6:0] PhyRB1;// Type 2-Distributed physical RB mapping for odd slots.

clocking cb @(posedge Clk);
default input #1step output #CQ;
output negedge nRst;
// Inputs
output Init; // Re-initialize the block
output UsedRBNum;// Length of type 2 distributed bitmap.
output PhyRB0;// Type 2-Distributed physical RB mapping for even slots.
output PhyRB1;// Type 2-Distributed physical RB mapping for odd slots.
output ResBlks;

endclocking

endinterface

module tb;
  import mytest::*;
  import uvm_pkg::*;
  parameter CLKPRD = 8; // Clock period
  parameter CQ = 0;
  reg Clk;

MyIf  uMyIf (
  // Clock & reset:
  .Clk(Clk)
);

initial begin
  Clk <= 0;
  forever #(CLKPRD/2) Clk = ~Clk;
end

initial begin
  uvm_config_db #(virtual MyIf)::set(null, "", "vif", uMyIf);
  run_test("ParamTest");
end

endmodule

Yet the randomization fails with this error:

** Failure: (vsim-7067) t2.sv(23): Index out of bounds (PhyRB[1][9]) for unpacked array of packed elements in constraint.

I tried to run QuestaSim with -solvedebug option, so it reports the following:

# Begin RandSet 1
# Random Variables:
#   bit signed [31:0] PhyRB[1].size
#   bit signed [31:0] PhyRB[0].size
# Constraints:
#   t2.sv(16): ArrSize { (PhyRB[0].size > 0); }
#   t2.sv(17): ArrSize { (PhyRB[0].size <= ResBlks); }
#   t2.sv(18): ArrSize { (PhyRB[1].size == PhyRB[0].size); }
#   t2.sv(12): (PhyRB[1].size >= 0);
#   t2.sv(12): (PhyRB[0].size >= 0);
# * Solving RandSet 1 with ACT engine
# Solved: PhyRB[0].size = 9
# Solved: PhyRB[1].size = 9
# End RandSet 1

I don't understand, why is the foreach statement attempting to access PhyRB[1][9], although PhyRB[1].size = 9 ?!

I am running QuestaSim 10.4c simulation tool.

\$\endgroup\$
1
\$\begingroup\$

The problem is in the foreach syntax, it should be:

foreach PhyRB[,i] PhyRB[0][i] < ResBlks;
| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.