Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / verif / env / fnx / vlib / CSRFmwork / src / CSRAccessor.vr
// ========== Copyright Header Begin ==========================================
//
// OpenSPARC T2 Processor File: CSRAccessor.vr
// Copyright (C) 1995-2007 Sun Microsystems, Inc. All Rights Reserved
// 4150 Network Circle, Santa Clara, California 95054, U.S.A.
//
// * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// For the avoidance of doubt, and except that if any non-GPL license
// choice is available it will apply instead, Sun elects to use only
// the General Public License version 2 (GPLv2) at this time for any
// software where a choice of GPL license versions is made
// available with the language indicating that GPLv2 or any later version
// may be used, or where a choice of which version of the GPL is applied is
// otherwise unspecified.
//
// Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
// CA 95054 USA or visit www.sun.com if you need additional information or
// have any questions.
//
// ========== Copyright Header End ============================================
#include "report_macros.vri"
class CSRAccessor extends AccessorBase {
//=================================================
// Constructor
//=================================================
task new ( CSRState ShadowState,
bit [CSRT_ADDR_OFFSET_WIDTH-1:0] input_addr_offset ,
bit [CSRT_DATA_WIDTH-1:0] input_por_value ,
bit [CSRT_DATA_WIDTH-1:0] input_rmask ,
bit [CSRT_DATA_WIDTH-1:0] input_read_only_mask ,
bit [CSRT_DATA_WIDTH-1:0] input_write_mask ,
bit [CSRT_DATA_WIDTH-1:0] input_clear_mask ,
bit [CSRT_DATA_WIDTH-1:0] input_set_mask ,
bit [CSRT_DATA_WIDTH-1:0] input_toggle_mask ,
string input_name ,
integer input_num_fields ,
CSRAccessMethod input_access_methods[],
integer input_access_level[],
string input_access_name[],
integer input_default_access_method
) {
super.new ( ShadowState,
input_addr_offset,
input_por_value,
input_rmask,
input_read_only_mask,
input_write_mask,
input_clear_mask,
input_set_mask,
input_toggle_mask,
input_name,
input_num_fields);
csr_check_enabled = CSRT_CHECK_ENABLED;
set_method_array(input_access_methods, input_access_level, input_access_name);
DefaultMethod = input_default_access_method;
} // end task new
//=================================================
// Read function
//=================================================
function bit [CSRT_DATA_WIDTH-1:0] read (integer method = CSRT_USE_DEFAULT_METHOD){
if (method == CSRT_USE_DEFAULT_METHOD)
method = DefaultMethod;
QuickReport(CSRReport, RTYP_CSR_DEBUG_1,"CSRAccessor: %s read(): %s register: Addr %0h",
get_method_name(method),
get_name(),
get_addr_offset());
check_method(method);
if (method == CSRT_STUB) {
QuickReport(CSRReport, RTYP_CSR_DEBUG_1,"CSRAccessor: Stub read of %s register: ", get_name());
} // end if CSRT_STUB
else {
read = access_methods[method].read(get_addr_offset());
}
} // end function read
//=================================================
// Write task
//=================================================
task write (bit [CSRT_DATA_WIDTH-1:0] csr_data, integer method = CSRT_USE_DEFAULT_METHOD ){
if (method == CSRT_USE_DEFAULT_METHOD)
method = DefaultMethod;
QuickReport(CSRReport, RTYP_CSR_DEBUG_1,"CSRAccessor: %s write(): %s register: Addr %0h : data %0h",
get_method_name(method),
get_name(),
get_addr_offset(),
csr_data);
check_method(method);
// Ensure only one modifying transaction per register
semaphore_get (WAIT, ShadowState.csr_write_trans_sem, 1);
// Perform Hardware Write
if (method != CSRT_STUB)
access_methods[method].write(get_addr_offset(), csr_data);
if (access_level[method] == CSRT_FULL_ACCESS || method == CSRT_OMNI) {
update_shadow_data (csr_data);
}
else if (access_level[method] == CSRT_HW_ACCESS) {
//Can not reliably update shadow state when register supports
//HW access control. It is up to the user to use set_shadow_csr.
//Setting X value will provide a trival match when comparing shadow state
update_shadow_data (64'hx);
}
else
QuickReport(CSRReport, RTYP_CSR_ALERT,"CSRAccessor::write: Unable to update shadow state for %s register using current access method ",
get_name());
semaphore_put (ShadowState.csr_write_trans_sem, 1);
QuickReport(CSRReport, RTYP_CSR_DEBUG_3,"%0d:CSRAccessor::write: %s register:\t%0h\n",get_cycle(),get_name(),csr_data);
} // end task write
//=================================================
// Check Register Function
//=================================================
// The following change was made on 9/21/01 -RFT
// This function should really be based on a wild card match, allowing
// a don't care setting for the shadow data. This is necessary for registers
// that don't have a specific POR value because they are not connected to
// reset.
//
function integer check_register (integer method = CSRT_USE_DEFAULT_METHOD) {
bit [CSRT_DATA_WIDTH-1:0] actual_data;
bit [CSRT_DATA_WIDTH-1:0] expected_data;
bit [CSRT_DATA_WIDTH-1:0] diff_vector = 64'h0;
integer index = 0;
bit success = 1;
if (method == CSRT_USE_DEFAULT_METHOD)
method = DefaultMethod;
if (csr_check_enabled) {
printf("inside csr_check_enabled \n");
actual_data = read(method);
expected_data = get_shadow_data();
while (index < CSRT_DATA_WIDTH) {
//If expected_data indicates a wildcard, then skip comparison
if (expected_data[index] !== 1'bx)
if (actual_data[index] !== expected_data[index]) {
diff_vector[index] = 1'b1;
success = 1'b0;
}
++index;
}
// After the actual data is screened for X's it is okay to apply a wildcard
// comparision. This allows expected data to contain the wildcards.
if (!success) {
//These are not report calls because there is no good way to print leading
//zeros in data without printing 512 bits by default.
QuickReport(CSRReport, RTYP_CSR_ERROR, "CSRAccessor::check_register:ERROR - %s REGISTER MISMATCHED.",
get_name() );
printf("\tACTUAL = 64'h%h\n\tEXPECTED = 64'h%h\n\tDiff Vector = 64'h%h\n",
actual_data,
expected_data,
diff_vector);
check_register = CSRT_MISMATCH_RETURN_CODE;
}
else
check_register = CSRT_SUCCESSFUL_RETURN_CODE;
printf("Data match: \tACTUAL = 64'h%h\n\tEXPECTED = 64'h%h\n\t",
actual_data,
expected_data);
} //check enabled
else {
QuickReport(CSRReport, RTYP_CSR_ALERT,"CSR %s REGISTER CHECKING DISABLED", get_name());
check_register = CSRT_SUCCESSFUL_RETURN_CODE;
}
} // end function check_register
//=================================================
// Reset Task
//=================================================
task reset () {
QuickReport(CSRReport, RTYP_CSR_DEBUG_3,"%0d:CSRAccessor::reset: %s register\t%0h",
get_cycle(),get_name(),get_por_value());
semaphore_get (WAIT, ShadowState.csr_write_trans_sem, 1);
set_shadow_data(get_por_value());
semaphore_put (ShadowState.csr_write_trans_sem, 1);
} // end task reset
//=================================================
// Read Field Function
//=================================================
function bit [CSRT_DATA_WIDTH-1:0] read_field ( integer field_id,
integer method = CSRT_USE_DEFAULT_METHOD) {
bit [CSRT_DATA_WIDTH-1:0] temp_data;
if (method == CSRT_USE_DEFAULT_METHOD)
method = DefaultMethod;
if (field_id < get_max_num_fields()) {
QuickReport(CSRReport, RTYP_CSR_DEBUG_3,"%0d:CSR read_field(): %s register %s field:\t%0h",
get_cycle(),get_name(),reg_field[field_id].get_field_name(),read_field);
temp_data = read(method);
temp_data = temp_data & reg_field[field_id].get_field_mask();
temp_data = temp_data >> reg_field[field_id].get_field_position();
read_field = temp_data;
}
else {
QuickReport(CSRReport, RTYP_CSR_ERROR, "CSRAccessor::read_field: Invalid field_id %0h", field_id);
}
} // end function read_field
//=================================================
// Write Field Task
//=================================================
task write_field ( integer field_id,
bit [CSRT_DATA_WIDTH-1:0] field_data,
integer method = CSRT_USE_DEFAULT_METHOD ) {
bit [CSRT_DATA_WIDTH-1:0] curr_data;
bit [CSRT_DATA_WIDTH-1:0] revised_data;
bit [CSRT_DATA_WIDTH-1:0] field_positioned_data;
bit [CSRT_DATA_WIDTH-1:0] zero_field_mask;
bit [CSRT_DATA_WIDTH-1:0] refresh_bit_mask;
if (method == CSRT_USE_DEFAULT_METHOD)
method = DefaultMethod;
if (field_id < get_max_num_fields()) {
QuickReport(CSRReport, RTYP_CSR_DEBUG_3,"%0d:CSR write_field(): %s register %s field:\t%0h",
get_cycle(),get_name(),reg_field[field_id].get_field_name(),field_data);
semaphore_get (WAIT, ShadowState.csr_write_trans_sem, 1);
field_positioned_data = reg_field[field_id].get_field_mask() & (field_data << reg_field[field_id].get_field_position());
curr_data = read(method);
zero_field_mask = ~(reg_field[field_id].get_field_mask());
refresh_bit_mask = zero_field_mask & get_write_mask ();
revised_data = (curr_data & refresh_bit_mask) | field_positioned_data;
if (access_level[method] == CSRT_FULL_ACCESS || method == CSRT_OMNI) {
update_shadow_data (revised_data);
}
else if (access_level[method] == CSRT_HW_ACCESS) {
//Can not reliably update shadow state when register supports
//HW access control. It is up to the user to use set_shadow_csr.
//Setting X value will provide a trival match when comparing shadow state
update_shadow_data (64'hx);
}
else
QuickReport(CSRReport, RTYP_CSR_ALERT,"CSRAccessor::write_field: Unable to update shadow state for %s register using current access method ",
get_name());
access_methods[method].write(get_addr_offset(), revised_data);
semaphore_put (ShadowState.csr_write_trans_sem, 1);
}
else {
QuickReport(CSRReport, RTYP_CSR_ERROR, "CSRAccessor::write_field: Invalid field_id %0h", field_id);
}
} // end task write_field
//=================================================
// Write Fields Task
//=================================================
task write_fields(CSRFieldAggregate field_aggregate, integer method = CSRT_USE_DEFAULT_METHOD, bit use_method_read = 0) {
bit [CSRT_DATA_WIDTH-1:0] curr_data;
bit [CSRT_DATA_WIDTH-1:0] revised_data;
bit [CSRT_DATA_WIDTH-1:0] field_positioned_data = 0;
bit [CSRT_DATA_WIDTH-1:0] zero_field_mask = 0;
bit [CSRT_DATA_WIDTH-1:0] refresh_bit_mask = 0;
CSRAggregateContainer field_container;
zero_field_mask = ~zero_field_mask;
if (method == CSRT_USE_DEFAULT_METHOD)
method = DefaultMethod;
semaphore_get (WAIT, ShadowState.csr_write_trans_sem, 1);
if (use_method_read)
curr_data = read(method);
else
curr_data = get_shadow_data();
field_container = field_aggregate.pop();
while (field_container != null) {
if (field_container.field_id < get_max_num_fields()) {
// CSRReport.report(RTYP_INFO,"%0d:CSR write_fields(): %s register %s field:\t%0h\n", get_cycle(), get_name(),
// reg_field[field_container.field_id].get_field_name(), field_container.field_data);
field_positioned_data |= (reg_field[field_container.field_id].get_field_mask() &
(field_container.field_data << reg_field[field_container.field_id].get_field_position()));
zero_field_mask &= ~(reg_field[field_container.field_id].get_field_mask());
refresh_bit_mask |= zero_field_mask & get_write_mask();
} else {
QuickReport(CSRReport, RTYP_CSR_ERROR, "CSRAccessor::write_fields: Invalid field_id %0h", field_container.field_id);
}
field_container = field_aggregate.pop();
}
revised_data = (curr_data & refresh_bit_mask) | field_positioned_data;
if (access_level[method] == CSRT_FULL_ACCESS || method == CSRT_OMNI) {
update_shadow_data (revised_data);
} else if (access_level[method] == CSRT_HW_ACCESS) {
//Can not reliably update shadow state when register supports HW access control. It is up to the user to use set_shadow_csr.
//Setting X value will provide a trival match when comparing shadow state
update_shadow_data (64'hx);
} else
QuickReport(CSRReport, RTYP_CSR_ALERT,"CSRAccessor: (write_fields) Unable to update shadow state for %s register using current access method",
get_name());
if (curr_data !== revised_data) {
QuickReport(CSRReport, RTYP_CSR_DEBUG_1,"CSRAccessor: %s write_fields(): %s register: Addr %0h : data %0h", get_method_name(method), get_name(),
get_addr_offset(), revised_data);
access_methods[method].write(get_addr_offset(), revised_data);
} else {
QuickReport(CSRReport, RTYP_CSR_DEBUG_1,"CSRAccessor: %s write_fields(): %s register: Addr %0h : data %0h %s", get_method_name(method),
get_name(), get_addr_offset(), revised_data, " -- Not writing due to current_data == new_data");
}
semaphore_put (ShadowState.csr_write_trans_sem, 1);
} // end task write_fields
//=================================================
// Set Shadow CSR Task
//=================================================
task set_shadow_csr(bit [CSRT_DATA_WIDTH-1:0] new_data, integer field_id = -1) {
bit [CSRT_DATA_WIDTH-1:0] curr_data;
bit [CSRT_DATA_WIDTH-1:0] revised_data;
bit [CSRT_DATA_WIDTH-1:0] field_positioned_data;
bit [CSRT_DATA_WIDTH-1:0] zero_field_mask;
semaphore_get (WAIT, ShadowState.csr_write_trans_sem, 1);
QuickReport(CSRReport, RTYP_CSR_DEBUG_1, "CSRAccessor: set_shadow_csr(): %s register: Addr %0h : data %0h",
get_name(), get_addr_offset(), new_data);
if (field_id == -1)
//No field specfied - set entire CSR
set_shadow_data (new_data);
else {
if (field_id < get_max_num_fields()) {
field_positioned_data = reg_field[field_id].get_field_mask() & (new_data << reg_field[field_id].get_field_position());
curr_data = get_shadow_data();
zero_field_mask = ~(reg_field[field_id].get_field_mask());
revised_data = (curr_data & zero_field_mask) | field_positioned_data;
set_shadow_data (revised_data);
}
else
QuickReport(CSRReport, RTYP_CSR_ALERT,"CSRAccessor::set_shadow_csr: Field ID out of range\n");
}
semaphore_put (ShadowState.csr_write_trans_sem, 1);
} // end task set_shadow_csr()
//=================================================
// Get Shadow CSR Function
//=================================================
function bit [CSRT_DATA_WIDTH-1:0] get_shadow_csr(integer field_id = -1) {
bit [CSRT_DATA_WIDTH-1:0] temp_data;
QuickReport(CSRReport, RTYP_CSR_DEBUG_1, "CSRAccessor: get_shadow_csr(): %s register: Addr %0h", get_name(), get_addr_offset());
if (field_id == -1)
//No field specfied - return entire CSR
get_shadow_csr = get_shadow_data();
else {
temp_data = get_shadow_data();
temp_data = temp_data & reg_field[field_id].get_field_mask();
temp_data = temp_data >> reg_field[field_id].get_field_position();
get_shadow_csr = temp_data;
}
} // end function get_shadow_csr()
} // end class CSRAccessor