Extend a base request class, pass the caller’s arguments to super.new, and add the subtype’s own checks.
Hardware context: Read, write and burst transaction classes used by a shared driver. Construct a read request with valid inherited identity and address state.
A new error-injecting transaction forgot to call super.new with its arguments. The compiler quietly inserted super.new() with no arguments, every object got ID 0, and the scoreboard’s duplicate-ID check fired on a correct DUT.
Write the class read_request, extending the supplied request_base. Its constructor takes requested_id and requested_address. The base keeps the ID and sets error bit 0 when the ID is outside 0 to 255. Your class adds the address checks: a legal read address is 0 to 65532 and a multiple of 4. Set error bit 1 for an address out of range, or else bit 2 for a misaligned one.
The object is valid only when no error bit is set; only then store the 16-bit address, otherwise address is 0. Keep the base fields: the same id, errors and valid, seen through a base handle or a derived one.
Signals in the timeline
| Signal | Width | Role |
|---|---|---|
requested_id | 32 | input of each check |
byte_address | 32 | input of each check |
Full specification
class request_base;
int id,errors;bit valid;
function new(input int requested_id=0);
id=requested_id;errors=(requested_id<0 || requested_id>255)?1:0;valid=(errors==0);
endfunction
endclass
class read_request extends request_base;
bit [15:0] address;
function new(input int requested_id, requested_address);
endclass
Each case builds a read_request, assigns it to a request_base handle, and reports valid and errors through both handles, the inherited id and the stored address.
Examples
Example 1
A valid read- Input
id = 7, address = 0x1004
- Output
base_view_valid = yes, derived_view_valid = yes, inherited_id = 7, address = 0x1004, base_view_errors = 'b00000000, derived_view_errors = 'b00000000
Both views are valid with id 7, address 0x1004 and no error bits.
Example 2
A bad ID survives a good address- Input
id = 300, address = 0x1004
- Output
base_view_valid = no, derived_view_valid = no, inherited_id = 300, address = 0x0, base_view_errors = 'b00000001, derived_view_errors = 'b00000001
The base sets error bit 0 for ID 300. The object is invalid, so the address is not stored.
Example 3
The subtype’s own check- Input
id = 9, address = 3
- Output
base_view_valid = no, derived_view_valid = no, inherited_id = 9, address = 0x0, base_view_errors = 'b00000100, derived_view_errors = 'b00000100
The address is in range but not a multiple of 4: error bit 2, seen through both handles.
Constraints and contract
- IDs and addresses are signed ints.
- An address error never hides an ID error: keep every bit that is set.
- Keep the class name, field name and constructor signature.
Hints
Hint 1
What does a derived constructor call when you do not call super.new yourself, and with which arguments?
Hint 2
The base sets errors and valid from the ID. Add your address bits to the same errors field, then work out valid again from all of them.
Hint 3
Call super.new with the requested ID first; check range before alignment; store the address only if the whole object is valid.
What this judge verifies: Your class is built with IDs and addresses on both sides of every limit, and each case reads it through a base handle and a derived one. Passing shows the inherited and added fields agree.
131 checks on Verilator · local server. Run the examples first, then check the full regression. The suite is local and inspectable. A passing result establishes the tested cases, not a proof for all possible inputs.
See all 5 steps and the final capstone