117 lines
4.6 KiB
Systemverilog
117 lines
4.6 KiB
Systemverilog
|
|
`ifndef CALC_SCOREBOARD_SV
|
||
|
|
`define CALC_SCOREBOARD_SV
|
||
|
|
|
||
|
|
//-----------------------------------------------------------------------------
|
||
|
|
// Calc1 scoreboard (self-checking, reference-model based - Vezba 10).
|
||
|
|
//
|
||
|
|
// For every transaction collected by the monitor, the embedded reference model
|
||
|
|
// (predictor) computes the expected response/result from the stimulus and
|
||
|
|
// compares it against what the DUT actually produced. Mismatches are reported
|
||
|
|
// as UVM_ERROR.
|
||
|
|
//-----------------------------------------------------------------------------
|
||
|
|
class calc_scoreboard extends uvm_scoreboard;
|
||
|
|
|
||
|
|
// control fields
|
||
|
|
bit checks_enable = 1;
|
||
|
|
bit coverage_enable = 1;
|
||
|
|
|
||
|
|
// TLM port connecting the scoreboard to the monitor
|
||
|
|
uvm_analysis_imp#(calc_seq_item, calc_scoreboard) item_collected_imp;
|
||
|
|
|
||
|
|
// bookkeeping
|
||
|
|
int unsigned num_of_tr;
|
||
|
|
int unsigned num_passed;
|
||
|
|
int unsigned num_failed;
|
||
|
|
|
||
|
|
`uvm_component_utils_begin(calc_scoreboard)
|
||
|
|
`uvm_field_int(checks_enable, UVM_DEFAULT)
|
||
|
|
`uvm_field_int(coverage_enable, UVM_DEFAULT)
|
||
|
|
`uvm_component_utils_end
|
||
|
|
|
||
|
|
function new(string name = "calc_scoreboard", uvm_component parent = null);
|
||
|
|
super.new(name,parent);
|
||
|
|
item_collected_imp = new("item_collected_imp", this);
|
||
|
|
endfunction : new
|
||
|
|
|
||
|
|
//--------------------------------------------------------------------------
|
||
|
|
// Reference model / predictor.
|
||
|
|
// Computes the expected response and result for a Calc1 command, following
|
||
|
|
// the functional specification (Vezba 5, Tabela 6/7/8).
|
||
|
|
// All arithmetic is unsigned.
|
||
|
|
//--------------------------------------------------------------------------
|
||
|
|
function void predict(input bit [CMD_WIDTH-1:0] cmd,
|
||
|
|
input bit [DATA_WIDTH-1:0] op1,
|
||
|
|
input bit [DATA_WIDTH-1:0] op2,
|
||
|
|
output bit [RESP_WIDTH-1:0] exp_resp,
|
||
|
|
output bit [DATA_WIDTH-1:0] exp_data);
|
||
|
|
bit [DATA_WIDTH:0] tmp; // one extra bit to catch carry/borrow
|
||
|
|
exp_data = '0;
|
||
|
|
case (cmd)
|
||
|
|
CMD_ADD : begin
|
||
|
|
tmp = {1'b0, op1} + {1'b0, op2};
|
||
|
|
if (tmp[DATA_WIDTH]) exp_resp = RESP_ERROR; // overflow
|
||
|
|
else begin exp_resp = RESP_SUCCESS; exp_data = tmp[DATA_WIDTH-1:0]; end
|
||
|
|
end
|
||
|
|
CMD_SUB : begin
|
||
|
|
if (op1 < op2) exp_resp = RESP_ERROR; // underflow
|
||
|
|
else begin exp_resp = RESP_SUCCESS; exp_data = op1 - op2; end
|
||
|
|
end
|
||
|
|
CMD_SHL : begin
|
||
|
|
exp_resp = RESP_SUCCESS;
|
||
|
|
exp_data = op1 << op2[4:0];
|
||
|
|
end
|
||
|
|
CMD_SHR : begin
|
||
|
|
exp_resp = RESP_SUCCESS;
|
||
|
|
exp_data = op1 >> op2[4:0];
|
||
|
|
end
|
||
|
|
default : begin
|
||
|
|
exp_resp = RESP_ERROR; // invalid command
|
||
|
|
end
|
||
|
|
endcase
|
||
|
|
endfunction : predict
|
||
|
|
|
||
|
|
//--------------------------------------------------------------------------
|
||
|
|
// Analysis-port callback: invoked by the monitor for each collected item.
|
||
|
|
//--------------------------------------------------------------------------
|
||
|
|
function void write(calc_seq_item tr);
|
||
|
|
bit [RESP_WIDTH-1:0] exp_resp;
|
||
|
|
bit [DATA_WIDTH-1:0] exp_data;
|
||
|
|
bit ok;
|
||
|
|
|
||
|
|
num_of_tr++;
|
||
|
|
if (!checks_enable) return;
|
||
|
|
|
||
|
|
predict(tr.cmd, tr.op1, tr.op2, exp_resp, exp_data);
|
||
|
|
|
||
|
|
// The result data is only meaningful for a successful operation.
|
||
|
|
ok = (tr.resp === exp_resp) &&
|
||
|
|
((exp_resp !== RESP_SUCCESS) || (tr.result === exp_data));
|
||
|
|
|
||
|
|
if (ok) begin
|
||
|
|
num_passed++;
|
||
|
|
`uvm_info(get_type_name(),
|
||
|
|
$sformatf("PASS: %s | expected resp=%0d data=0x%08h",
|
||
|
|
tr.convert2string(), exp_resp, exp_data), UVM_HIGH)
|
||
|
|
end
|
||
|
|
else begin
|
||
|
|
num_failed++;
|
||
|
|
`uvm_error(get_type_name(),
|
||
|
|
$sformatf("MISMATCH on port %0d, cmd=%s op1=0x%08h op2=0x%08h : expected resp=%0d data=0x%08h, got resp=%0d data=0x%08h",
|
||
|
|
tr.port+1, tr.cmd2string(), tr.op1, tr.op2,
|
||
|
|
exp_resp, exp_data, tr.resp, tr.result))
|
||
|
|
end
|
||
|
|
endfunction : write
|
||
|
|
|
||
|
|
function void report_phase(uvm_phase phase);
|
||
|
|
`uvm_info(get_type_name(),
|
||
|
|
$sformatf("Scoreboard examined %0d transactions: %0d passed, %0d failed",
|
||
|
|
num_of_tr, num_passed, num_failed), UVM_LOW)
|
||
|
|
if (num_failed != 0)
|
||
|
|
`uvm_warning(get_type_name(),
|
||
|
|
$sformatf("%0d transaction(s) did NOT match the reference model", num_failed))
|
||
|
|
endfunction : report_phase
|
||
|
|
|
||
|
|
endclass : calc_scoreboard
|
||
|
|
|
||
|
|
`endif
|