`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