// Literatur: Vorlesungsunterlagen AMV von Rainer Findenig (FH-Hagenberg) // Coverage ... Grad der Abdeckung // Covergroups & Coverpoints bit mysignal2; int mysignal3; covergroup mycg @(myEvent); label1: coverpoint mysignal1; label2: coverpoint mysignal2 { bins enabled = { 1 }; bins disabled = { 0 }; } label3: coverpoint mysignal3 { bins firstSection = { 0, 1, 2 }; bins secondSection = { 10, 20, 30 }; bins other = default; } label4: coverpoint mysignal4 { // bins die nicht betrachtet werden ignore_bins zero = {0}; ... // bins die nicht auftreten sollten/duerfen illegal_bins invalid = default; ... // Transition Coverage: // wie oft wurden bestimmte Uebergaenge ausgefuehrt bins posEdge = ( 0 => 1 ); bins negEdge = ( 1 => 0 ); bins nothing = ( 0 => 0 ), ( 1 => 1 ); } // Conditional Coverage: Bsp. keine Infos waehrend Reset label5: coverpoint mysignal5 iff (!rst); endgroup mycg cg = new; // Objekt muss angelegt werden mycg = new; // Cross Coverage covergroup cg_opcodes @(posedge clk); val_cmd: coverpoint cmd { bins arith = { ... }; bins logic_ = { ... }; ... } val_reg: coverpoint regaddr; cmd_with_reg: cross val_cmd, val_reg; // Illegale Kombinationen markieren // Bsp. logische Operationen duerfen Register 0 nicht nuetzen cmd_with_reg: cross val_cmd, val_reg { illegal_bins log_r0 = binsof(val_cmd.logi_) && binsof(val_reg) intersect {0}; } endgroup // Bereiche Betrachten int regaddr; ... covergroup somecg @(someevent); reg_address: coverpoint regaddr { bins zero = { 0 }; // 1 bin bins local_ [] = { [1:7] }; // 7 bins: local_[1]..local_[7] bins in = { [8:15] }; // 1 bin bins out [] = { [16:24] }; // 8 bins bins invalid = default; } endgroup // zufaellig generierte Werte typedef enum { NOP=0, SLEEP=1, LOADI=2, LOAD=3, STORE=4, JUMP=8, JUMPC=10, JUMPZ=11, MOVE=12, AND=16, OR=17, XOR=18, NOT=19, ADD=20, ADDC=21, SUB=22, SUBC=23, COMP=24, INC=26, DEC=27, SHL=28, SHR=29, SHLC=30, SHRC=31 } aProl16Command; typedef bit [REGISTER_WIDTH-1 : 0] aData_v; class clProl16Opcode; rand int ra; rand int rb; rand aProl16Command cmd; rand aData_v data; // rand ... zufaellige Werte // randc ... zufaellige Werte, wiederholt Werte erst // wenn bereits alle vorgekommen constraint no_invalid_model_cmd { cmd != NOP; cmd != SLEEP; cmd != LOAD; cmd != STORE; }; constraint only_valid_regA { ra >= 0; ra < REGISTER_NR; }; constraint only_valid_regB { rb >= 0; rb < REGISTER_NR; }; function void pre_randomize(); begin $write("pre_randomize: Called for randomizing data."); end endfunction function void post_randomize(); begin $write("post_randomize: Called after randomizing data."); end endfunction endclass ... opcode = new (); void'(opcode.randomize()); // void damit keine Warnings ausgegeben werden opcode.randomize() with { cmd == NOP; }; // Constraints steuern opcode.only_valid_regA::constraint_mode(0); // Constraint aus opcode.only_valid_regA::constraint_mode(1); // Constraint ein opcode::constraint_mode(0); // Constraint Modus auslesen int on = opcode.only_valid_regA::constraint_mode(); opcode.only_valid_regA::rand_mode(0); // Random-Funkt. aus int on = opcode.only_valid_regA::rand_mode(); // auslesen // weitere Constraints constraint array_size { data.size() <= 8; }; constraint id_not_null { id != 0; }; constraint c { // inclusive src_port inside { [8'h0:8'hA],8'h14,8'h18 }; // exclusive ! (des_port inside { [8'h4:8'hFF] }); } constraint len { length dist { [64 : 127 ] := 10, // mindestens 10x im Bereich 64-127 [128 : 511 ] := 10, // ... [512 : 2048] := 10 }; } constraint src { src_port dist { 0 := 1, 1 := 1, 2 := 5, 4 := 1 }; } // gewichtete Distribution: constraint high_id { id dist { [0 : 0x400] :/ 25, // 25% im Bereich 0-0x400 [0x401 , 0x800] :/ 75 // 75% im Bereich 0x401-0x800 } } // bedingte Constraints constraint my_const { (id == 0) -> data.size() >= 2; (id == 100) -> data.size() == 0; if (size == RUNT) { length >= 0; length <= 63; } else if (size == OVERSIZE) { length >= 1501; length <= 5000; } }; // Iterative Constraints constraint frame_sizes { data.size inside {[1:10]}; // im Bereich 1-10 foreach (data[i]) // bekommt jedes Element ein data[i] == i; // eigenes Constraint } // Variable Ordnung der Constraints constraint frame_sizes { solve zero before data.size; // zuvor wird zero ausgewertet, zero -> data.size == 0; // danach data.size data.size inside {[0:10]}; foreach (data[i]) data[i] == i; } // zufaelliges Abarbeiten eines Zweiges task do_randcase(); begin randcase 20 : begin // 20 gibt das Gewicht $write ("first randcase \n"); // dieses Zweiges an end // (aus Summe berechnet) 20 : begin $write ("second randcase \n"); end 20 : begin $write ("third randcase\n"); end endcase end endtask