-
Notifications
You must be signed in to change notification settings - Fork 792
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[dv,membkdr] Updating membackdoor loading utilities #20864
base: integrated_dev
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -37,6 +37,13 @@ class mem_bkdr_util extends uvm_object; | |
protected uint32_t addr_lsb; | ||
protected uint32_t addr_width; | ||
protected uint32_t byte_addr_width; | ||
protected uint32_t non_ecc_bits_per_subword; | ||
protected uint32_t ecc_bits_per_subword; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think we actually use this variable (except where it gets its value). Maybe it could be a local there? |
||
protected uint32_t bits_per_subword; | ||
protected uint32_t subwords_per_word; | ||
protected uint32_t redundant_bits_per_entry; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you add a doc comment somewhere (maybe above the constructor) which explains what some of these numbers mean? Also, is there a difference in meaning between "entry" and "word" here? If not, it would probably be clearer to standardise on one of them. |
||
protected uint32_t interleave_bits_in_entry; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a yes/no flag, right? Can't it just be a |
||
protected uint32_t scramble_before_integ; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Similarly, I think this can just be a bit. |
||
|
||
// Address range of this memory in the system address map. | ||
protected addr_range_t addr_range; | ||
|
@@ -62,6 +69,8 @@ class mem_bkdr_util extends uvm_object; | |
// package. | ||
function new(string name = "", string path, int unsigned depth, | ||
longint unsigned n_bits, err_detection_e err_detection_scheme, | ||
int scramble_before_integ = 0, | ||
int redundant_bits_per_entry = 0, int interleave_bits_in_entry = 0, | ||
int extra_bits_per_subword = 0, int unsigned system_base_addr = 0); | ||
|
||
bit res; | ||
|
@@ -72,7 +81,10 @@ class mem_bkdr_util extends uvm_object; | |
|
||
this.path = path; | ||
this.depth = depth; | ||
this.width = n_bits / depth; | ||
this.interleave_bits_in_entry = interleave_bits_in_entry; | ||
this.scramble_before_integ = scramble_before_integ; | ||
this.redundant_bits_per_entry = redundant_bits_per_entry; | ||
this.width = (n_bits / depth) - redundant_bits_per_entry; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We've already got a check that |
||
this.err_detection_scheme = err_detection_scheme; | ||
|
||
if (`HAS_ECC) begin | ||
|
@@ -81,11 +93,11 @@ class mem_bkdr_util extends uvm_object; | |
import prim_secded_pkg::get_ecc_parity_width; | ||
|
||
prim_secded_e secded_eds = prim_secded_e'(err_detection_scheme); | ||
int non_ecc_bits_per_subword = get_ecc_data_width(secded_eds); | ||
int ecc_bits_per_subword = get_ecc_parity_width(secded_eds); | ||
int bits_per_subword = non_ecc_bits_per_subword + ecc_bits_per_subword + | ||
extra_bits_per_subword; | ||
int subwords_per_word; | ||
non_ecc_bits_per_subword = get_ecc_data_width(secded_eds); | ||
ecc_bits_per_subword = get_ecc_parity_width(secded_eds); | ||
bits_per_subword = non_ecc_bits_per_subword + ecc_bits_per_subword + | ||
extra_bits_per_subword; | ||
Comment on lines
+98
to
+99
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I had to read this twice to get the syntax tree! :-) Could you add some parens around the broken line? |
||
//int subwords_per_word; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You've moved this variable to a field in the class. Probably need to delete this line too. |
||
|
||
// We shouldn't truncate the actual data word. This check ensures that err_detection_scheme | ||
// and width are related sensibly. This only checks we've got enough space for one data word | ||
|
@@ -107,7 +119,7 @@ class mem_bkdr_util extends uvm_object; | |
|
||
byte_width = `HAS_PARITY ? 9 : 8; | ||
bytes_per_word = data_width / byte_width; | ||
`DV_CHECK_LE_FATAL(bytes_per_word, 32, "data width > 32 bytes is not supported") | ||
// `DV_CHECK_LE_FATAL(bytes_per_word, 32, "data width > 32 bytes is not supported") | ||
Comment on lines
-110
to
+122
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is this commented? (Is it no longer true? In which case, we should probably just delete it, but I'm not sure I understand the logic yet) |
||
size_bytes = depth * bytes_per_word; | ||
addr_lsb = $clog2(bytes_per_word); | ||
addr_width = $clog2(depth); | ||
|
@@ -212,10 +224,29 @@ class mem_bkdr_util extends uvm_object; | |
bit res; | ||
uint32_t index; | ||
uvm_hdl_data_t data; | ||
uvm_hdl_data_t raw_data; | ||
|
||
if (!check_addr_valid(addr)) return 'x; | ||
|
||
index = addr >> addr_lsb; | ||
|
||
res = uvm_hdl_read($sformatf("%0s[%0d]", path, index), data); | ||
`DV_CHECK_EQ(res, 1, $sformatf("uvm_hdl_read failed at index %0d", index)) | ||
|
||
|
||
// Adjust the row data for interleaving. Was interleaved, beg back to true position | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure what "beg" means here (that's probably not the verb you intend! :-D) I'd probably also avoid the "row" name. I don't think that the code in |
||
if (interleave_bits_in_entry) begin | ||
raw_data = data; | ||
for (int subword_idx = 0; subword_idx < subwords_per_word; subword_idx++) begin | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This loop is inverse with the one in I'd suggest moving the contents into a helper function. I think it would probably make things a bit easier to follow. |
||
for (int b= 0; b < bits_per_subword; b++) begin | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: Missing space before the '=' |
||
int true_col_pos; | ||
int intrlv_col_pos; | ||
intrlv_col_pos = (subword_idx + (((b * 4) + 1) * 4)); | ||
true_col_pos = (subword_idx * bits_per_subword) + b; | ||
Comment on lines
+242
to
+245
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd probably suggest folding these lines together, so you end up with something like: int true_col_pos = (subword_idx + (((b * 4) + 1) * 4));
int intrlv_col_pos = (subword_idx * bits_per_subword) + b; |
||
data[true_col_pos] = raw_data[intrlv_col_pos]; | ||
end | ||
end | ||
end | ||
return data; | ||
endfunction | ||
|
||
|
@@ -325,8 +356,26 @@ class mem_bkdr_util extends uvm_object; | |
virtual function void write(bit [bus_params_pkg::BUS_AW-1:0] addr, uvm_hdl_data_t data); | ||
bit res; | ||
uint32_t index; | ||
uvm_hdl_data_t raw_data; | ||
if (!check_addr_valid(addr)) return; | ||
index = addr >> addr_lsb; | ||
|
||
// Adjust the row data for interleaving | ||
// Data passed in assumes subwords in contiguous locations | ||
// Data to be written is converted to interleaved position | ||
// (note the interleaving function may be different for differen memory structures | ||
if (interleave_bits_in_entry) begin | ||
raw_data = data; | ||
for (int subword_idx = 0; subword_idx < subwords_per_word; subword_idx++) begin | ||
for (int b= 0; b < bits_per_subword; b++) begin | ||
int true_col_pos; | ||
int intrlv_col_pos; | ||
intrlv_col_pos = (subword_idx + (((b * 4) + 1) * 4)); | ||
true_col_pos = (subword_idx * bits_per_subword) + b; | ||
data[intrlv_col_pos] = raw_data[true_col_pos]; | ||
end | ||
end | ||
end | ||
res = uvm_hdl_deposit($sformatf("%0s[%0d]", path, index), data); | ||
`DV_CHECK_EQ(res, 1, $sformatf("uvm_hdl_deposit failed at index %0d", index)) | ||
endfunction | ||
|
@@ -379,9 +428,26 @@ class mem_bkdr_util extends uvm_object; | |
|
||
// this is used to write 32bit of data plus 7 raw integrity bits. | ||
virtual function void write39integ(bit [bus_params_pkg::BUS_AW-1:0] addr, logic [38:0] data); | ||
uvm_hdl_data_t row_data; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: Double space. |
||
uint32_t word_idx; | ||
uint32_t byte_idx; | ||
uint32_t subword_idx; | ||
|
||
`_ACCESS_CHECKS(addr, 32) // this is essentially an aligned 32bit access. | ||
if (!check_addr_valid(addr)) return; | ||
write(addr, data); | ||
|
||
// read-modify-write: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm, this needs a bit of thought. We're adding RMW functionality which wasn't there before. (Notice that there isn't any Can you explain (possibly in a comment) why |
||
// Each entry may have more than one subword chunk stored | ||
// So we get current data row and insert the new subword at the right location, | ||
// The modified data is then written back | ||
word_idx = addr >> addr_lsb; | ||
byte_idx = addr - (word_idx << addr_lsb); | ||
subword_idx = byte_idx >> 2; | ||
// Note the read function eliminates interleaving, if used, and returns data in the contiguous locations | ||
row_data = read(addr); | ||
row_data[subword_idx * 39 +:39]= data; | ||
// Note the write function takes care of interleaving, if used. | ||
write(addr, row_data); | ||
endfunction | ||
|
||
virtual function void write64(bit [bus_params_pkg::BUS_AW-1:0] addr, logic [63:0] data); | ||
|
@@ -561,17 +627,50 @@ class mem_bkdr_util extends uvm_object; | |
`uvm_info(`gfn, "Randomizing mem contents", UVM_LOW) | ||
for (int i = 0; i < depth; i++) begin | ||
uvm_hdl_data_t data; | ||
uvm_hdl_data_t raw_data; | ||
`DV_CHECK_STD_RANDOMIZE_FATAL(data, "Randomization failed!", path) | ||
raw_data = data; | ||
`uvm_info(`gfn, $sformatf("Randomizing mem contents: \n Pre ECC Data is %h, \n Index: i: %d", | ||
raw_data, i), | ||
UVM_DEBUG) | ||
if (`HAS_PARITY) begin | ||
uvm_hdl_data_t raw_data = data; | ||
for (int byte_idx = 0; byte_idx < bytes_per_word; byte_idx++) begin | ||
bit raw_byte = raw_data[byte_idx * 8 +: 8]; | ||
bit parity = (err_detection_scheme == ParityOdd) ? ~(^raw_byte) : (^raw_byte); | ||
data[byte_idx * 9 +: 9] = {parity, raw_byte}; | ||
end | ||
end else begin | ||
data = get_ecc_computed_data(data); | ||
// There may be multiple subwords within each row/entry. | ||
// Need to update the randomized data for each subword chunk in a Row | ||
for (int subword_idx = 0; subword_idx < subwords_per_word; subword_idx++) begin | ||
logic [31:0] raw_subword; | ||
logic [38:0] raw_subword_with_ecc; | ||
|
||
// Get the raw data subword chunk without ECC from the input data | ||
for (int b= 0; b < non_ecc_bits_per_subword; b++) | ||
raw_subword[b] = raw_data[b+(subword_idx * non_ecc_bits_per_subword)]; | ||
|
||
// Compute the ECC Code | ||
raw_subword_with_ecc = get_ecc_computed_data(raw_subword); | ||
`uvm_info(`gfn, | ||
$sformatf("Randomizing mem contents: \n\ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
Pre ECC subword: %h \n\ | ||
Post ECC subword: %h \n\ | ||
Index: i: %d", | ||
raw_subword, raw_subword_with_ecc, i), | ||
UVM_DEBUG) | ||
// Place the subword with ECC data at the right slot within the data to be written | ||
for (int b= 0; b < bits_per_subword; b++) begin | ||
int column_position; | ||
column_position = ((subword_idx * bits_per_subword) + b); | ||
data[column_position] = raw_subword_with_ecc[b]; | ||
end | ||
end | ||
end | ||
`uvm_info(`gfn, $sformatf("Randomizing mem contents: \n\ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
Post ECC Data is %h,\ | ||
Index: i: %d", | ||
data, i), UVM_DEBUG) | ||
write(i * bytes_per_word, data); | ||
end | ||
endfunction | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs to be removed as it is needed in the local environment