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.

asked Aug 11, 2019 at 6:38
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

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

foreach PhyRB[,i] PhyRB[0][i] < ResBlks;
answered Aug 12, 2019 at 2:16
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.