| Login | | Don't have an account yet? You can create one. As a registered user you have some advantages like theme manager, comments configuration and post comments with your name. | |
| Who's Online | There are currently, 71 guest(s) and 1 member(s) that are online.
You are Anonymous user. You can register for free by clicking here | |
 | |
|
Verification Guild: Forums |
|
| View previous topic :: View next topic |
| Author |
Message |
war_isbest Senior


Joined: Dec 05, 2007 Posts: 21
|
Posted: Mon Jan 21, 2013 12:49 am Post subject: Instruction sequence generator |
|
|
Dear friends,
I need some help in constrainsts.
I created a base class inst_class with all properties defined by the instruction architecture and a method to form the instruction based on opcode type selected (eg. arith, control etc).
I created a scenario class which has a dynamic array of the inst_class named items[].
the base scenario class is extended by common instruction scenario class which has constraints to create valid sequences.
the common instruction scenario class is extended by dep_scenario which has more constraints to force instruction with dependency.
the common instruction scenario class is extended by arith_scenario which has more constraints to generate only arithmetic instruction.
In the ENV class i have a queue(named scenario_c) of type common instruction scenario.
Now the generation happens like this.
Program block creates few objects of type arith_scenario, dep_scenario and common_scenario and pushes down the queue.
In the ENV class i have run task which goes like this:
foreach scenario_c[i]
for (j=0;j<scenario_c.length<j++)
begin
scenario_c[i].items[j]=new;
scenario_c[i].items[j].randomize();
scenario_c[i].items[j].form_instr();
end
Now he problem is the constriaints of arith_scenario, dep_scenario and common_scenario are not passed to inst_class.
How can i do that.
Plz help |
|
| Back to top |
|
 |
war_isbest Senior


Joined: Dec 05, 2007 Posts: 21
|
Posted: Wed Jan 23, 2013 11:42 pm Post subject: plz help |
|
|
| Dear friends kindly reply. |
|
| Back to top |
|
 |
miket Senior


Joined: Jan 12, 2004 Posts: 31 Location: Ottawa, Ontario, Canada
|
Posted: Mon Jan 28, 2013 8:04 am Post subject: |
|
|
Since we're shameless plugging papers here, I will put in a plug for a collegaue's paper on this topic. It was presented at SNUG, so this link will not work unless you are a Synopsys customer:
https://www.synopsys.com/news/pubs/snug/2012/canada/mc1_paper_elms.pdf
Alas, there is little discussion about the Reference Model in this paper. My strong recommendation there would be to create a TLM at the highest level of abstraction you can get away with. (Actually, that's my default position on all Reference Models, but doubly so in this case.)
--mike |
|
| Back to top |
|
 |
Hans Senior


Joined: Dec 17, 2003 Posts: 50 Location: Ottawa, Ontario, Canada
|
Posted: Mon Jan 28, 2013 9:02 am Post subject: Re: Instruction stream generation |
|
|
Rather interesting to see that this thread continues to be alive.
I don't know the paper miket just shamelessly plugged as I have no access to it, but it's from a trusted source (hey miket, long time no see ) so you should go get it to help with your instruction stream modeling challenges.
Safe from that, it sounds pretty conclusive that your current model does not enable polymorphism to have your inst_class take on the constraints of the derived scenario classes. But you would have to share additional code details (all class implementations you mention) to pinpoint the problem.
- HvdS |
|
| Back to top |
|
 |
war_isbest Senior


Joined: Dec 05, 2007 Posts: 21
|
Posted: Sun Feb 03, 2013 1:40 pm Post subject: Kindly put the paper |
|
|
Dear mike,
Kindly provide a direct link of the paper or email me at
waris.mohammad@gmail.com |
|
| Back to top |
|
 |
war_isbest Senior


Joined: Dec 05, 2007 Posts: 21
|
Posted: Sun Feb 03, 2013 1:43 pm Post subject: |
|
|
Dear hans,
I may nt be able to put the whole code.
Is it ok if i put the structure of each class? |
|
| Back to top |
|
 |
Hans Senior


Joined: Dec 17, 2003 Posts: 50 Location: Ottawa, Ontario, Canada
|
Posted: Sun Feb 03, 2013 1:50 pm Post subject: |
|
|
| Just putting the structure will in this particular case probably not suffice. You would have to include the relevant class data members, i.e. those involved or 'should-be' involved in some sort of 'factory pattern/override' applied to enable the polymorphism |
|
| Back to top |
|
 |
war_isbest Senior


Joined: Dec 05, 2007 Posts: 21
|
Posted: Mon Feb 04, 2013 11:39 pm Post subject: code snippets |
|
|
| Code: | ///inst_class.sv//////
`include "../tb/verilog/typedef_operation.sv"
class inst_class;
static int count = 0;
int id;///an id for each instruction
rand kind_e kind;
rand opcode_type_e opcode_type;
rand logic[1:0] op;
rand logic[3:0] cond;
rand logic[2:0] op2;
rand logic[5:0] op3;
rand logic[8:0]opf;
rand logic[8:0] opc;
//and many more properties
constraint opcode_type_valid{
(opcode_type==CALLt)-> kind inside {CALL};
(opcode_type==SETHIt)-> kind inside {SETHI};
(opcode_type==CONTROL)-> kind inside {BA,BEQ,Bicc,FBFCC};
(opcode_type==ALU)-> kind inside {ADD,ADDX,ADDcc,ADDXcc,TADDcc,TADDccTV,SUB,SUBcc,
SUBX,SUBXcc,AND,ANDcc,OR,ORcc,XOR,XORcc,
ANDN,ANDNcc,ORN,ORNcc,XNOR,XNORcc,SLL,SRL,SRA,JMPL};
(opcode_type==FPU)-> kind inside {FADDS};
(opcode_type==LD_ST)-> kind inside {LDW,STW};
(opcode_type==MULTIC)-> kind inside {UMUL,SMUL,UMULcc,SMULcc};
}
function new ();//(virtual pipe_if ifc);
//this.ifc=ifc;
id = count++;
endfunction:new
constraint legal_ALU
{
if (op==2'b10)
{
(kind == ADD) -> op3== 6'h00;
kind == AND -> op3 == 6'h01;
kind == OR -> op3 == 6'h02;
kind == XOR -> op3 == 6'h03;
kind == SUB -> op3 == 6'h04;
kind == ANDN -> op3 == 6'h05;
kind == ORN -> op3 == 6'h06;
kind == XNOR -> op3 == 6'h07;
//etc etc
}
}
task form_inst;
if(opcode_type==CALLt)instr={2'b01,disp30};
else if (opcode_type==CONTROL )instr={2'b00,a_bit,cond,op2,disp22};
else if(opcode_type==ALU )
begin
instr=((i_bit)) ?
{2'b10,rd,op3,rs1,i_bit,simm13}:
{2'b10,rd,op3,rs1,i_bit,asi,rs2};
if(op3==6'b111001 || op3==6'b111000)///JMPL and RETT
begin
$info("operand1+operand2=%h",(operand1+ operand2));
end
if(kind==JMPL)
begin
instr=((i_bit)) ?// or LD_ST add later
{2'b10,rd,6'h38,rs1,i_bit,simm13}:
{2'b10,rd,6'h38,rs1,i_bit,asi,rs2};
`ifdef _DEBUG
$info("JMPL selected");
`endif
end
end
else if (opcode_type==SETHIt)
begin
instr={2'b00,rd,3'b100,imm22};//sethi
end
else if(opcode_type==LD_ST)instr={2'b11,rd,op3,rs1,i_bit,asi,rs2};
else if(opcode_type==FPU)instr={2'b10,rd,6'h34,rs1,opf,rs2};//op3=h35 for fpcmp
else instr=32'h01000000;//nop
$info("formed instruction=%h id=%d kind=%s opcode_type=%s",instr,id,kind,opcode_type);
endtask:form_inst
endclass
///scenario.sv///////
`include "../tb/verilog/inst_class.sv"
class instruction_scenario extends inst_class;
rand int unsigned scenario_kind;
rand int unsigned length=50;
rand inst_class items[];
rand int unsigned repeated;
function int unsigned define_scenario (string name,
int unsigned max_len);
$info("secenario is %s",name);
this.length=max_len;
endfunction
endclass
//////////////////common_instruction_scenario.sv///
`include "../tb/verilog/scenario.sv"
class common_instruction_scenario extends instruction_scenario;
constraint three_CTI_bad
{
foreach(items[i]){
if(i>1){
if((items[i].opcode_type==CONTROL) && (items[i-1].opcode_type==CONTROL))
{
items[i-2].opcode_type!=CONTROL;
}
}
}
}
endclass
//////////////////////////////////////////////////////////
///////dep_scenario.sv//////////
`include "../tb/verilog/common_scenario.sv"
class dep_scenario extends common_instruction_scenario;
int SCN_MORE_DEP;
int base_addr, addr_range;
constraint more_dep_scn_valid {
//check below line 15/10/12
if (scenario_kind == SCN_MORE_DEP) {
repeated == 0; length == 10;
foreach (items[i]) {
items[i].rd inside {[base_addr : base_addr+addr_range]};
items[i].rs1 inside {[base_addr : base_addr+addr_range]};
items[i].rs2 inside {[base_addr : base_addr+addr_range]};
}
}
}
//constraint depcheck
//{
// items[23].kind ==BA ;
//}
function new;
super.new();
this.base_addr = 0;
this.addr_range = 4;
this.SCN_MORE_DEP = define_scenario ("SCN_MORE_DEP", 40);
endfunction
function void pre_randomize ();
super.pre_randomize();
this.base_addr = 0;
this.addr_range = 4;
endfunction
endclass
class arith_only_scn extends common_instruction_scenario;
int SCN_ARITH_ONLY;
constraint arith_only_scn_valid {
if (scenario_kind == SCN_ARITH_ONLY) {
repeated == 0;
length inside {[5:10]};
foreach (items[i]) {
foreach (items[i]) {
items[i].opcode_type == ALU;
}
}
}
}
function new ();
super.new();
this.SCN_ARITH_ONLY = define_scenario ("SCN_ARITH_ONLY", 30);
endfunction
endclass
//////////////////////////////////
/////////////////////////////////
///env.sv/////////
//`include "../tb/verilog/inst_class.sv"
//`include "../tb/verilog/instr_packet.sv"
//`include "../tb/verilog/common_scenario.sv"
`include"../tb/verilog/drv_inst.sv"
//`include"../tb/verilog/drv.sv"
`include"../tb/verilog/interfaces.sv"
`include"../tb/verilog/regfile_mon.sv"
`include"../tb/verilog/checker_sb.sv"
class env;
instruction_scenario scenario_set[$];
static int number_comm_scn;
virtual pipe_if ifc;
virtual model_if ifm;
event handshake;
mailbox mb_g2d,regf2sb,mod2sb;
drv_inst drv;
regfile_mon regmon;
checker_sb checkb;
//drv dv;
static int mbcnt,basic_scn_no;
function new(virtual pipe_if ifc,virtual model_if ifm,mailbox mod2sb);
mb_g2d=new;
regf2sb=new;
this.mod2sb=mod2sb;// initialized in pgm block
this.ifc=ifc;
this.ifm=ifm;
drv=new(ifc,ifm,mb_g2d);
regmon=new(ifc,regf2sb );
checkb=new(ifc,regf2sb,mod2sb);
mbcnt=0;
//drv=new(ifc,ifm);
basic_scn_no=$urandom_range(5,100);
endfunction
task config_proc;
inst_class i1,i2,i3,i4,i5;
number_comm_scn=$urandom_range(1,100);
i1=new;
i2=new;
// some code to config the processor for a mode eg. cache disable
//
//
$info("configuration_over");
endtask:config_proc
task generator_good( mailbox mbx);
inst_class instruction;
foreach(scenario_set[i])
begin
scenario_set[i].items=new[scenario_set[i].length];
for(int j=0;j<scenario_set[i].length;j++)
scenario_set[i].items[j]=new;
end
foreach(scenario_set[i])
assert(scenario_set[i].randomize()) else $fatal(0, "Instruction::randomize failed");
foreach(scenario_set[i])
begin
for(int j=0;j<scenario_set[i].length;j++)
begin
scenario_set[i].items[j].form_inst;
$display("GEN: Sending instruction with id=%d", scenario_set[i].items[j].id);
`ifdef _ALUTEST///when verifying ALU
if(scenario_set[i].items[j].opcode_type==ALU )
begin
`ifdef _DEBUG
$info("entering ALU thread");
$info("drive instruction =%h with op1= %h and op2 =%h and rd=%d and id=%d",scenario_set[i].items[j].instr,scenario_set[i].items[j].operand1,scenario_set[i].items[j].operand2,scenario_set[i].items[j].rd,scenario_set[i].items[j].id);
`endif
mbx.put(scenario_set[i].items[j]);
`ifdef _DEBUG
$info("sending ALU instruction");
`endif
end
else mbx.put(scenario_set[i].items[j]); // Send transaction to driver
`endif
end
end
endtask
task run;
generator_good(mb_g2d);
//gen.run_rcv(handshake);
endtask:run
task runrcv;
drv.run_rcv;
//dv.drv_fetch(handshake);
endtask:runrcv
endclass
////////////////////////////////////
//////pgm_pipe.sv////
`timescale 1ns/1ns
//`include"../tb/interfaces.sv"
//`include"$HOME_32b_hdl/pipe_mod.sv"
`include"../tb/verilog/instr_packet.sv"
`include "../tb/verilog/dep_scenario.sv"
`include "../tb/verilog/proc_model.sv"
`include "../tb/verilog/env.sv"
program automatic pgm_pipe (
model_if if_d,pipe_if pr
);
bit termination_condition=1'b0;
//pipe_ir mod;
mailbox mod2sb;
decode_model mod_proc;
env env_p;
arith_only_scn scn_arith;
common_instruction_scenario basic_scenario ;
dep_scenario scn_dep;
initial begin : execution_of_main_tb
scn_arith=new;
//init_regs_scn scn_regs = new;
basic_scenario = new;
scn_dep=new;
//mod=new(pr,if_d);
mod2sb=new;
mod_proc=new(pr,if_d,mod2sb);
env_p=new(pr,if_d,mod2sb);
// repeat (5) begin
env_p.scenario_set.push_back (scn_dep);
// to give the scn_arith scenario a little more weight \u263a
// end
// foreach(env_p.scenario_set[i])env_p.scenario_set[i]=new
// repeat (10) begin
env_p.scenario_set.push_back (scn_arith);
// end
basic_scenario.length=100;
repeat (env_p.basic_scn_no) begin
env_p.scenario_set_c.push_back (basic_scenario);
end
wait(pr.reset);
//fork
while(1)
begin
repeat (1) @ (posedge pr.pl_clk);
// fork //uncomment for cheker
fork
mod_proc.run;
env_p.runrcv;
join
// env_p.checkb.compare; //uncomment for cheker
// join_any //uncomment for cheker
if(termination_condition)
break;
// join_any
end
$display("all instructions processed");
$display("-----end of test------");
$finish;
end : execution_of_main_tb
initial
begin
while(1)
begin
repeat (1) @ (posedge pr.pl_clk);
@(negedge (pr.d_en_ip)) env_p.regmon.run_mon;
if(termination_condition)
break;
end
end
//////checker
initial
begin
wait(pr.reset);
while(1)
begin
repeat (1) @ (posedge pr.pl_clk);
env_p.checkb.compare;
if(termination_condition)
break;
end
end
initial begin
termination_condition=1'b0;
#1000000
termination_condition=1'b1;
end
initial
begin
pr.reset=1'b0;
#100
pr.reset=1'b1;//reset removal
env_p.config_proc;
$display("-----start of test------");
// while(1)
// begin
// repeat (1) @ (posedge pr.pl_clk);
env_p.run;
$info("instruction generation completed");
// if(termination_condition)
// break;
// end
end
endprogram : pgm_pipe
|
|
|
| Back to top |
|
 |
Hans Senior


Joined: Dec 17, 2003 Posts: 50 Location: Ottawa, Ontario, Canada
|
Posted: Tue Feb 05, 2013 9:16 am Post subject: |
|
|
I just had a look at your code. Here are few comments for you to ponder, followed at the end by what I think is the crux of your problem.
First, this instruction and instruction scenario generation code much resembles the (original) VMM scenario generation solution. Whether derived from it or not, it would behoove you to consult the documentation on VMM scenario generation. It includes a description and examples on how to override scenario items and scenarios in the basic scenario descriptor and generator classes. There is also a 2007 SNUG paper on the topic co-authored by myself - quite a good paper in my own humble opinion. You can get it from Synopsys from their SNUG archives, or a quick Google on the title returns the following links:
http://www.docin.com/p-237268624.html
http://bbs.eetop.cn/thread-257345-1-1.html
Secondly, and more concretely with respect to your code, a few observations:
Why does your instruction_scenario class (the base scenario class) extend from inst_class (the 'item' class)? The former models a sequence of items but is not an item itself. It does not seem to be harmful in the end but does add unnecessary overhead to your scenario classes.
You do a `include on common_scenario.sv somewhere. Is this a typo and should it be `include common_instruction_scenario.sv? This brings me to the question as to whether this code provided actually compiles and runs (except for the proper functioning of the constraints).
Lastly, and to your original question, if you reconsider your code from the env class:
| Code: |
foreach scenario_c[i]
for (j=0;j<scenario_c.length<j++)
begin
scenario_c[i].items[j]=new;
scenario_c[i].items[j].randomize();
scenario_c[i].items[j].form_instr();
end
|
then you should realize that you are only ever randomizing individual items (scenario_c[i].items[j].randomize()) outside of the scenario context and thus not taking in scnenario level constraints.
To accomplish what you want you need to randomize at the scenario level, i.e. scenario_c[i].randomize(). This does require that you 'prefill' the items array for any given scenario so that it has length > 0 and each item in it is actually not null (i.e. is newed). You do this in fact in your 'generator_good' task, so seeing the name of this task you may have already figured out the remedy to your problem.
So this is the way to do it. Now, their are better (in terms of reuse etc.) ways to organize your instruction scenario generation code. Again for this refer to the scenario or sequence generator solutions in the different verification methodologies like VMM, or much more prevalent these days of course, the UVM. If you are really stuck on creating your home grown solution, then consider a plain SystemVerilog solution with comparable reuse characteristics described in a DVCon paper from a few years back, "Advanced Stimulus Generation Using Scenarios". You can get it from tjhis link - http://www.xtreme-eda.com/downloads-technical-library.html#section1
I apologize (not really, ) for the couple of shameless plugs I threw in here (the paper references), though I do honestly think these are very decent paper references on the topic.
If you have any more questions and would like to discuss in more detail, please indicate and we can continue communicating privately.
Regards - Hans |
|
| Back to top |
|
 |
war_isbest Senior


Joined: Dec 05, 2007 Posts: 21
|
Posted: Wed Feb 06, 2013 12:38 am Post subject: plz email the pdfs |
|
|
Can you please email the pdf of the first 2 links.
Yes this code is inspired by a paper from SNUG for which i got the link in this forum.
Thanks for pointing out the randomization mistakes.
Regarding moving to VMM/UVM , it may take some time for me as i have just started learning UVM material from verificationacadamy.com.
No trainings yet.
regards
waris
email: waris.mohammad@gmail.com |
|
| Back to top |
|
 |
Hans Senior


Joined: Dec 17, 2003 Posts: 50 Location: Ottawa, Ontario, Canada
|
Posted: Wed Feb 06, 2013 7:22 am Post subject: |
|
|
I'll send you the PDFs privately.
Hans |
|
| Back to top |
|
 |
war_isbest Senior


Joined: Dec 05, 2007 Posts: 21
|
Posted: Thu Feb 07, 2013 12:23 am Post subject: randomization failed |
|
|
Dear friends,
I changed the code to scenario_set[i].randomize().
now the simulator (questasim 10.0b) gives internal error just before randomization.
Are there any conflicting constraints in my code ?? |
|
| Back to top |
|
 |
Hans Senior


Joined: Dec 17, 2003 Posts: 50 Location: Ottawa, Ontario, Canada
|
Posted: Thu Feb 07, 2013 7:09 am Post subject: |
|
|
Your nested foreach constraint for arith scenarios looks off; there is no 2nd iterator.
Other than that it is difficult to see without running oneself where things might actually be going wrong - could be various places - happy debug! |
|
| Back to top |
|
 |
war_isbest Senior


Joined: Dec 05, 2007 Posts: 21
|
Posted: Wed Feb 13, 2013 2:42 am Post subject: right method of writing a constraint |
|
|
Dear friends
Which of the below method is correct for writing a constraint if i want CALL-> ALU sequence?
| Code: |
foreach(items[i])
{
if(i%2 ){
items[i].opcode_type=CALL;
items[i+1].opcode_type=ALU;
}
}
|
OR
| Code: |
foreach(items[i])
{
if(i%2 ){
items[i].opcode_type=CALL;
foreach(items[j] && j=i+1)
{
items[j].opcode_type=ALU;
}
}
}
|
|
|
| Back to top |
|
 |
Hans Senior


Joined: Dec 17, 2003 Posts: 50 Location: Ottawa, Ontario, Canada
|
Posted: Wed Feb 13, 2013 7:12 am Post subject: |
|
|
The first one looks fine, but will not work I think for an items array with odd length. You'd have to add the condition that "items.size() % 2 == 0".
The second constraint should work I think.
Your constraint solver will have debug modes that you can use to help resolve solver failures |
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
| |
|
|