Choose a few inputs that make four broken copies of a mismatch formatter give themselves away.
Hardware context: Regression diagnostics for a tagged bus or DMA transaction stream. Choose diagnostic inputs that separate a correct mismatch formatter from copies with planted formatting bugs.
A mismatch message is only useful if it is right. Your team's format_mismatch builds lines like ID=7 WIDTH=8 EXP=00x1z001 GOT=00x1z101 from a transaction ID, a width and two strings of bit symbols.
The version in the specification is correct. Four copies of it each hide one bug. Your job is to write the tests that expose them: in the task stimulus, call try_format once for each input you want to try. You may try at most three inputs.
For every input, the correct formatter and each broken copy run side by side. A broken copy is caught when its message differs from the correct one on at least one of your inputs. After each run you see which copies you caught and what each bug was.
Choose inputs that exercise every rule: the ID limits, the letter case of x and z, the string lengths, and values that differ.
Signals in the timeline
| Signal | Width | Role |
|---|---|---|
hidden_bug | 8 | input of each check |
Full specification
// Symbols are 0, 1, x, X, z and Z. X and Z are printed in lowercase.
function automatic bit symbolic_bits(input string text, input int width);
if (text.len() != width) return 0;
for (int i = 0; i < text.len(); i++)
if (text[i] != "0" && text[i] != "1" && text[i] != "x" && text[i] != "X" && text[i] != "z" && text[i] != "Z") return 0;
return 1;
endfunction
function automatic string lowercase(input string text);
string out;
out = "";
for (int i = 0; i < text.len(); i++)
out = $sformatf("%s%c", out, (text[i] == "X" || text[i] == "Z") ? text[i] + 8'd32 : text[i]);
return out;
endfunction
function automatic string format_mismatch(input int id, width, input string expected_bits, observed_bits);
if (id < 0 || id > 255) return "ERR:ID";
if (width < 1 || width > 32) return "ERR:WIDTH";
if (!symbolic_bits(expected_bits, width)) return "ERR:EXPECTED";
if (!symbolic_bits(observed_bits, width)) return "ERR:OBSERVED";
return $sformatf("ID=%0d WIDTH=%0d EXP=%s GOT=%s", id, width, lowercase(expected_bits), lowercase(observed_bits));
endfunction
task automatic stimulus();
try_format(7, 8, "00x1z001", "00X1Z101"); // one call per input
endtask
Legal ID is 0 to 255 and width is 1 to 32. Both strings must have exactly width characters from 0, 1, x, X, z and Z. A legal input returns ID=<id> WIDTH=<width> EXP=<expected> GOT=<observed>, with X and Z printed in lowercase. Otherwise the result is ERR:ID, ERR:WIDTH, ERR:EXPECTED or ERR:OBSERVED, checked in that order.
Your inputs may be legal or not, since invalid inputs are part of the formatter's job. The only rules for you: at most 3 calls, and each string at most 40 characters long.
Examples
Example 1
Your inputs follow the rules- Input
stimulus() makes 2 calls; every string is 4 characters
- Output
inputs_legal = yes
Two calls is within the limit of three, and no string is longer than 40 characters.
Example 2
A broken copy is caught by one differing message- Input
try_format(255, 4, "0X1Z", "1x0z")
- Output
caught = yes
The correct formatter prints ID=255 WIDTH=4 EXP=0x1z GOT=1x0z. A copy that prints anything else for this input is caught.
Example 3
Rejections count as results too- Input
try_format(8, 4, "0011", "01")
- Output
caught = yes
The observed string has 2 symbols but width is 4, so the correct result is ERR:OBSERVED. A copy that formats it instead is caught.
Constraints and contract
- Call try_format at most 3 times inside stimulus.
- Each string argument is at most 40 characters.
- Do not call format_mismatch yourself; the comparison runs on every input you add.
Hints
Hint 1
Read the correct formatter rule by rule. For each rule, ask what input would make a version that gets that rule wrong print something different.
Hint 2
One input can catch several bugs at once if it is unusual in several ways: an extreme ID, uppercase symbols and two values that differ.
Hint 3
Error paths count too. An input that should be rejected is just as useful as one that should be printed.
What this judge verifies: Your inputs are run through the correct formatter and four broken copies, and the messages are compared character by character. Passing shows your inputs separate each broken copy from the correct one.
5 checks on Icarus Verilog · browser. 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 6 steps and the final capstone