1157 lines
37 KiB
Markdown
1157 lines
37 KiB
Markdown
# Fall 2026 DV Onboarding Test Plan
|
|
|
|
<!--
|
|
Make two copies of this template:
|
|
1. testplan_initial.md, submitted before implementing tests.
|
|
2. testplan_final.md, updated after implementation and coverage closure.
|
|
|
|
Keep the initial copy unchanged after review. HTML comments are editing
|
|
instructions and disappear from rendered Markdown.
|
|
-->
|
|
## NOTE: THIS IS A TEMPLATE FOR YOU TO FOLLOW. THIS IS **NOT** A COMPREHENSIVE TESTPLAN. YOU NEED TO EXTEND IT.
|
|
## Document information
|
|
|
|
| Field | Value |
|
|
| --------------------- | ------------------------------ |
|
|
| Verification engineer | Dylan Benzi, benziboy, dbenzi3 |
|
|
| Plan revision | Initial |
|
|
| Date | 2026-09-26 |
|
|
|
|
### Revision history
|
|
|
|
| Revision | Date | Changes |
|
|
| -------- | ---------- | ----------------------------------------------------------------------- |
|
|
| Initial | 2026-09-26 | Initial planned tests |
|
|
| Final | YYYY-MM-DD | <!-- Tests or constraints added after debugging and coverage review --> |
|
|
|
|
## 1. Functional tests
|
|
|
|
<!--
|
|
Plan tests for the CPU functionality supported by this onboarding. Organize
|
|
related behavior together. Include both individual instruction behavior and
|
|
multi-instruction sequences where ordering or dependencies matter.
|
|
|
|
Add as many rows and detailed test records as needed. Do not put every CPU
|
|
operation into one large program: each failure should identify a reasonably
|
|
small area to debug.
|
|
-->
|
|
|
|
### Functional-test summary
|
|
|
|
#### Implemented ISA to test
|
|
- ADD
|
|
- ADDI
|
|
- SUB
|
|
- LW
|
|
- SW
|
|
- BEQ
|
|
- SLL
|
|
- SRL
|
|
- EBREAK
|
|
|
|
| Test ID | Test name | Functionality being tested | Expected result | Status |
|
|
| ------- | ---------------------- | ---------------------------------------- | --------------------------------- | ------- |
|
|
| 1.1 | add overflow | add two regs causing an overflow | overflow discarded | Planned |
|
|
| 1.2 | addi overflow | add imm to reg causing an overflow | overflow discarded | Planned |
|
|
| 1.3 | addi negative | add negative imm | imm is subtracted | Planned |
|
|
| 1.4 | add typical | add two regs | regs added properly | Planned |
|
|
| 1.5 | addi typical | add imm to reg | imm added properly | Planned |
|
|
| 1.6 | addi negative overflow | add negative numbers causing an overflow | negative overflow wrap around | Planned |
|
|
| 1.7 | sub overflow | subtract two regs causing an overflow | negative overflow wrap around | Planned |
|
|
| 1.8 | sub typical | subtract two regs | regs subtracted properly | Planned |
|
|
| 1.9 | sll oob | shift left by larger than 2^5 bits | left shift constrainted to 2^5 | Planned |
|
|
| 1.10 | srl oob | shift right by larger than 2^5 bits | right shift constrainted to 2^5 | Planned |
|
|
| 1.11 | sll zero | shift left by zero bits | no shift | Planned |
|
|
| 1.12 | srl zero | shift right by zero bits | no shift | Planned |
|
|
| 1.13 | sll one | shift left by one bit | logical left shift by one bit | Planned |
|
|
| 1.14 | srl one | shift right by one bit | logical right shift by one bit | Planned |
|
|
| 1.15 | sll typical | shift left by <2^5 bits | correct logical left shift | Planned |
|
|
| 1.16 | srl typical | shift right by <2^5 bits | correct logical right shift | Planned |
|
|
| 1.17 | lw zero offset | lw with zero offset | zero offset computed | Planned |
|
|
| 1.18 | sw zero offset | sw with zero offset | zero offset computed + stored | Planned |
|
|
| 1.19 | lw positive | lw with positive offset | correct offset computed | Planned |
|
|
| 1.20 | sw positive | sw with positive offset | correct offset computed + stored | Planned |
|
|
| 1.21 | lw negative | lw with negative offset | correct offset computed | Planned |
|
|
| 1.22 | sw negative | sw with negative offset | correct offset computed + stored | Planned |
|
|
| 1.23 | lw x0 | lw into x0 reg | write discarded, x0 remains 0 | Planned |
|
|
| 1.24 | beq x0 | beq with both regs as x0 | take branch | Planned |
|
|
| 1.25 | beq not taken | beq with non-equal regs | branch not taken | Planned |
|
|
| 1.26 | beq typical | beq with equal regs | branch taken | Planned |
|
|
| 1.27 | ebreak immediately | ebreak as first instruction | halt CPU | Planned |
|
|
|
|
### Functional-test details
|
|
|
|
### 1.1 — `add overflow`
|
|
|
|
**Functionality:** add two registers together that would cause an overflow
|
|
|
|
**Initial state:**
|
|
|
|
- Registers: x1 = 0xFFFFFFFF, x2 = 0xFFFFFFFF
|
|
- Data memory: none
|
|
- Other setup: none
|
|
|
|
**Program:**
|
|
|
|
<!-- Use the same representation that will be placed in run_member_directed_tests(). -->
|
|
|
|
```systemverilog
|
|
prog = '{
|
|
// asm_instr(.op(...), .rd(...), .rs1(...), .rs2(...), .imm(...)),
|
|
asm_instr(.op(OP_ADDI), .rd(1), .rs1(0), .imm(-1)),
|
|
asm_instr(.op(OP_ADDI), .rd(2), .rs1(0), .imm(-1)),
|
|
asm_instr(.op(OP_ADD), .rd(2), .rs1(1), .rs2(2)),
|
|
EBREAK_WORD
|
|
};
|
|
```
|
|
|
|
**Expected result:**
|
|
|
|
| Register or memory word | Expected value | Calculation or explanation |
|
|
| ----------------------- | -------------- | ------------------------------------------------------------------- |
|
|
| `x2` | `32'hFFFFFFFE` | 0xFFFFFFFF + 0xFFFFFFFF = 0x(1)FFFFFFFE, the leading 1 is truncated |
|
|
|
|
**Pass criteria:** 3 cycle operation
|
|
|
|
**Final result:** <!-- Complete in testplan_final.md: pass/fail and useful log or waveform reference. -->
|
|
|
|
### 1.2 — `addi overflow`
|
|
|
|
**Functionality:** add an immediate to a register that would cause an overflow
|
|
|
|
**Initial state:**
|
|
|
|
- Registers: x1 = 0xFFFFFFFF
|
|
- Data memory: none
|
|
- Other setup: none
|
|
|
|
**Program:**
|
|
|
|
<!-- Use the same representation that will be placed in run_member_directed_tests(). -->
|
|
|
|
```systemverilog
|
|
prog = '{
|
|
// asm_instr(.op(...), .rd(...), .rs1(...), .rs2(...), .imm(...)),
|
|
asm_instr(.op(OP_ADDI), .rd(1), .rs1(0), .imm(-1)),
|
|
asm_instr(.op(OP_ADDI), .rd(1), .rs1(1), .imm(1)),
|
|
EBREAK_WORD
|
|
};
|
|
```
|
|
|
|
**Expected result:**
|
|
|
|
| Register or memory word | Expected value | Calculation or explanation |
|
|
| ----------------------- | -------------- | ------------------------------------------------------------ |
|
|
| `x1` | `32'h00000000` | 0xFFFFFFFF + 0x1 = 0x(1)00000000, the leading 1 is truncated |
|
|
|
|
**Pass criteria:** 2 cycle operation
|
|
|
|
**Final result:** <!-- Complete in testplan_final.md: pass/fail and useful log or waveform reference. -->
|
|
|
|
### 1.3 — `addi negative`
|
|
|
|
**Functionality:** adds a negative value to a register using addi, effectively subtracting from that register
|
|
|
|
**Initial state:**
|
|
|
|
- Registers: x1 = 0x1
|
|
- Data memory: none
|
|
- Other setup: none
|
|
|
|
**Program:**
|
|
|
|
<!-- Use the same representation that will be placed in run_member_directed_tests(). -->
|
|
|
|
```systemverilog
|
|
prog = '{
|
|
// asm_instr(.op(...), .rd(...), .rs1(...), .rs2(...), .imm(...)),
|
|
asm_instr(.op(OP_ADDI), .rd(1), .rs1(0), .imm(1)),
|
|
asm_instr(.op(OP_ADDI), .rd(1), .rs1(1), .imm(-1)),
|
|
EBREAK_WORD
|
|
};
|
|
```
|
|
|
|
**Expected result:**
|
|
|
|
| Register or memory word | Expected value | Calculation or explanation |
|
|
| ----------------------- | -------------- | -------------------------- |
|
|
| `x1` | `32'h0` | 0x1 - 0x1 = 0x0 |
|
|
|
|
**Pass criteria:** 2 cycle operation
|
|
|
|
**Final result:** <!-- Complete in testplan_final.md: pass/fail and useful log or waveform reference. -->
|
|
|
|
### 1.4 — `add typical`
|
|
|
|
**Functionality:** add two registers with values that will not cause an overflow
|
|
|
|
**Initial state:**
|
|
|
|
- Registers: x1 = 0x123, x2 = 0x123
|
|
- Data memory: none
|
|
- Other setup: none
|
|
|
|
**Program:**
|
|
|
|
<!-- Use the same representation that will be placed in run_member_directed_tests(). -->
|
|
|
|
```systemverilog
|
|
prog = '{
|
|
// asm_instr(.op(...), .rd(...), .rs1(...), .rs2(...), .imm(...)),
|
|
asm_instr(.op(OP_ADDI), .rd(1), .rs1(0), .imm(0x123)),
|
|
asm_instr(.op(OP_ADDI), .rd(2), .rs1(0), .imm(0x123)),
|
|
asm_instr(.op(OP_ADD), .rd(2), .rs1(1), .rs2(2)),
|
|
EBREAK_WORD
|
|
};
|
|
```
|
|
|
|
**Expected result:**
|
|
|
|
| Register or memory word | Expected value | Calculation or explanation |
|
|
| ----------------------- | -------------- | -------------------------- |
|
|
| `x2` | `32'h246` | 0x123 + 0x123 = 0x246 |
|
|
|
|
**Pass criteria:** 3 cycle operation
|
|
|
|
**Final result:** <!-- Complete in testplan_final.md: pass/fail and useful log or waveform reference. -->
|
|
|
|
### 1.5 — `addi typical`
|
|
|
|
**Functionality:** addi with immediate added to register without causing an overflow
|
|
|
|
**Initial state:**
|
|
|
|
- Registers: none
|
|
- Data memory: none
|
|
- Other setup: none
|
|
|
|
**Program:**
|
|
|
|
<!-- Use the same representation that will be placed in run_member_directed_tests(). -->
|
|
|
|
```systemverilog
|
|
prog = '{
|
|
// asm_instr(.op(...), .rd(...), .rs1(...), .rs2(...), .imm(...)),
|
|
asm_instr(.op(OP_ADDI), .rd(1), .rs1(0), .imm(0x123)),
|
|
EBREAK_WORD
|
|
};
|
|
```
|
|
|
|
**Expected result:**
|
|
|
|
| Register or memory word | Expected value | Calculation or explanation |
|
|
| ----------------------- | -------------- | -------------------------- |
|
|
| `x1` | `32'h123` | 0x0 + 0x123 = 0x123 |
|
|
|
|
**Pass criteria:** 1 cycle operation
|
|
|
|
**Final result:** <!-- Complete in testplan_final.md: pass/fail and useful log or waveform reference. -->
|
|
|
|
### 1.6 — `addi negative overflow`
|
|
|
|
**Functionality:** addi with a negative number causes an overflow wrap around to the register
|
|
|
|
**Initial state:**
|
|
|
|
- Registers: x1 = 0x0
|
|
- Data memory: none
|
|
- Other setup: none
|
|
|
|
**Program:**
|
|
|
|
<!-- Use the same representation that will be placed in run_member_directed_tests(). -->
|
|
|
|
```systemverilog
|
|
prog = '{
|
|
// asm_instr(.op(...), .rd(...), .rs1(...), .rs2(...), .imm(...)),
|
|
asm_instr(.op(OP_ADDI), .rd(1), .rs1(0), .imm(-1)),
|
|
EBREAK_WORD
|
|
};
|
|
```
|
|
|
|
**Expected result:**
|
|
|
|
| Register or memory word | Expected value | Calculation or explanation |
|
|
| ----------------------- | -------------- | ------------------------------------------------- |
|
|
| `x1` | `32'hFFFFFFFF` | 0x0 - 0x1 = 0xFFFFFFFF, overflow back to full reg |
|
|
|
|
**Pass criteria:** 1 cycle operation
|
|
|
|
**Final result:** <!-- Complete in testplan_final.md: pass/fail and useful log or waveform reference. -->
|
|
|
|
### 1.7 — `sub overflow`
|
|
|
|
**Functionality:** sub registers that would cause an overflow wrap around
|
|
|
|
**Initial state:**
|
|
|
|
- Registers: x1 = 0x1
|
|
- Data memory: none
|
|
- Other setup: none
|
|
|
|
**Program:**
|
|
|
|
<!-- Use the same representation that will be placed in run_member_directed_tests(). -->
|
|
|
|
```systemverilog
|
|
prog = '{
|
|
// asm_instr(.op(...), .rd(...), .rs1(...), .rs2(...), .imm(...)),
|
|
asm_instr(.op(OP_ADDI), .rd(1), .rs1(0), .imm(1)),
|
|
asm_instr(.op(OP_SUB), .rd(1), .rs1(0), .rs2(1)),
|
|
EBREAK_WORD
|
|
};
|
|
```
|
|
|
|
**Expected result:**
|
|
|
|
| Register or memory word | Expected value | Calculation or explanation |
|
|
| ----------------------- | ---------------- | ------------------------------------------- |
|
|
| `x1` | `32'hFFFFFFFF` | 0x0 - 0x1 = 0xFFFFFFFF overflow wrap around |
|
|
|
|
**Pass criteria:** 2 cycle operation
|
|
|
|
**Final result:** <!-- Complete in testplan_final.md: pass/fail and useful log or waveform reference. -->
|
|
|
|
### 1.8 — `sub typical`
|
|
|
|
**Functionality:** sub two registers without causing an overflow
|
|
|
|
**Initial state:**
|
|
|
|
- Registers: x1 = 0x123, x2 = 0x23
|
|
- Data memory: none
|
|
- Other setup: none
|
|
|
|
**Program:**
|
|
|
|
<!-- Use the same representation that will be placed in run_member_directed_tests(). -->
|
|
|
|
```systemverilog
|
|
prog = '{
|
|
// asm_instr(.op(...), .rd(...), .rs1(...), .rs2(...), .imm(...)),
|
|
asm_instr(.op(OP_ADDI), .rd(1), .rs1(0), .imm(0x123)),
|
|
asm_instr(.op(OP_ADDI), .rd(2), .rs1(0), .imm(0x23)),
|
|
asm_instr(.op(OP_SUB), .rd(2), .rs1(1), .rs2(2)),
|
|
EBREAK_WORD
|
|
};
|
|
```
|
|
|
|
**Expected result:**
|
|
|
|
| Register or memory word | Expected value | Calculation or explanation |
|
|
| ----------------------- | -------------- | -------------------------- |
|
|
| `x2` | `32'h100` | 0x123 - 0x23 = 0x100 |
|
|
|
|
**Pass criteria:** 3 cycle operation
|
|
|
|
**Final result:** <!-- Complete in testplan_final.md: pass/fail and useful log or waveform reference. -->
|
|
|
|
### 1.9 — `srl oob`
|
|
|
|
**Functionality:** srl masks to bottom 5 bits of data only, cannot shift more than 31
|
|
|
|
**Initial state:**
|
|
|
|
- Registers: x1 = 0xFFFFFFFF, x2 = 0x20
|
|
- Data memory: none
|
|
- Other setup: none
|
|
|
|
**Program:**
|
|
|
|
<!-- Use the same representation that will be placed in run_member_directed_tests(). -->
|
|
|
|
```systemverilog
|
|
prog = '{
|
|
// asm_instr(.op(...), .rd(...), .rs1(...), .rs2(...), .imm(...)),
|
|
asm_instr(.op(OP_ADDI), .rd(1), .rs1(0), .imm(-1)),
|
|
asm_instr(.op(OP_ADDI), .rd(2), .rs1(0), .imm(32)),
|
|
asm_instr(.op(OP_SRL), .rd(1), .rs1(1), .rs2(2)),
|
|
EBREAK_WORD
|
|
};
|
|
```
|
|
|
|
**Expected result:**
|
|
|
|
| Register or memory word | Expected value | Calculation or explanation |
|
|
| ----------------------- | -------------- | -------------------------- |
|
|
| `x1` | `32'hFFFFFFFF` | 0x20 == 2^5 => no shift |
|
|
|
|
**Pass criteria:** 3 cycle operation
|
|
|
|
**Final result:** <!-- Complete in testplan_final.md: pass/fail and useful log or waveform reference. -->
|
|
|
|
### 1.10 — `sll oob`
|
|
|
|
**Functionality:** sll masks to bottom 5 bits of data only, cannot shift more than 31
|
|
|
|
**Initial state:**
|
|
|
|
- Registers: x1 = 0xFFFFFFFF, x2 = 0x20
|
|
- Data memory: none
|
|
- Other setup: none
|
|
|
|
**Program:**
|
|
|
|
<!-- Use the same representation that will be placed in run_member_directed_tests(). -->
|
|
|
|
```systemverilog
|
|
prog = '{
|
|
// asm_instr(.op(...), .rd(...), .rs1(...), .rs2(...), .imm(...)),
|
|
asm_instr(.op(OP_ADDI), .rd(1), .rs1(0), .imm(-1)),
|
|
asm_instr(.op(OP_ADDI), .rd(2), .rs1(0), .imm(32)),
|
|
asm_instr(.op(OP_SLL), .rd(1), .rs1(1), .rs2(2)),
|
|
EBREAK_WORD
|
|
};
|
|
```
|
|
|
|
**Expected result:**
|
|
|
|
| Register or memory word | Expected value | Calculation or explanation |
|
|
| ----------------------- | -------------- | -------------------------- |
|
|
| `x1` | `32'hFFFFFFFF` | 0x20 == 2^5 => no shift |
|
|
|
|
**Pass criteria:** 3 cycle operation
|
|
|
|
**Final result:** <!-- Complete in testplan_final.md: pass/fail and useful log or waveform reference. -->
|
|
|
|
### 1.11 — `sll zero`
|
|
|
|
**Functionality:** sll with zero, causing no shift
|
|
|
|
**Initial state:**
|
|
|
|
- Registers: x1 = 0xFFFFFFFF
|
|
- Data memory: none
|
|
- Other setup: none
|
|
|
|
**Program:**
|
|
|
|
<!-- Use the same representation that will be placed in run_member_directed_tests(). -->
|
|
|
|
```systemverilog
|
|
prog = '{
|
|
// asm_instr(.op(...), .rd(...), .rs1(...), .rs2(...), .imm(...)),
|
|
asm_instr(.op(OP_ADDI), .rd(1), .rs1(0), .imm(-1)),
|
|
asm_instr(.op(OP_SLL), .rd(1), .rs1(1), .rs2(0)),
|
|
EBREAK_WORD
|
|
};
|
|
```
|
|
|
|
**Expected result:**
|
|
|
|
| Register or memory word | Expected value | Calculation or explanation |
|
|
| ----------------------- | -------------- | ------------------------------ |
|
|
| `x1` | `32'hFFFFFFFF` | 0xFFFFFFFF << 0x0 = 0xFFFFFFFF |
|
|
|
|
**Pass criteria:** 2 cycle operation
|
|
|
|
**Final result:** <!-- Complete in testplan_final.md: pass/fail and useful log or waveform reference. -->
|
|
|
|
### 1.12 — `srl zero`
|
|
|
|
**Functionality:** srl with zero, causing no shift
|
|
|
|
**Initial state:**
|
|
|
|
- Registers: x1 = 0xFFFFFFFF
|
|
- Data memory: none
|
|
- Other setup: none
|
|
|
|
**Program:**
|
|
|
|
<!-- Use the same representation that will be placed in run_member_directed_tests(). -->
|
|
|
|
```systemverilog
|
|
prog = '{
|
|
// asm_instr(.op(...), .rd(...), .rs1(...), .rs2(...), .imm(...)),
|
|
asm_instr(.op(OP_ADDI), .rd(1), .rs1(0), .imm(-1)),
|
|
asm_instr(.op(OP_SRL), .rd(1), .rs1(1), .rs2(0)),
|
|
EBREAK_WORD
|
|
};
|
|
```
|
|
|
|
**Expected result:**
|
|
|
|
| Register or memory word | Expected value | Calculation or explanation |
|
|
| ----------------------- | -------------- | ------------------------------ |
|
|
| `x1` | `32'hFFFFFFFF` | 0xFFFFFFFF << 0x0 = 0xFFFFFFFF |
|
|
|
|
**Pass criteria:** 2 cycle operation
|
|
|
|
**Final result:** <!-- Complete in testplan_final.md: pass/fail and useful log or waveform reference. -->
|
|
|
|
### 1.13 — `sll one`
|
|
|
|
**Functionality:** sll with one, causing a shift once to the left
|
|
|
|
**Initial state:**
|
|
|
|
- Registers: x1 = 0xFFFFFFFF, x2 = 0x1
|
|
- Data memory: none
|
|
- Other setup: none
|
|
|
|
**Program:**
|
|
|
|
<!-- Use the same representation that will be placed in run_member_directed_tests(). -->
|
|
|
|
```systemverilog
|
|
prog = '{
|
|
// asm_instr(.op(...), .rd(...), .rs1(...), .rs2(...), .imm(...)),
|
|
asm_instr(.op(OP_ADDI), .rd(1), .rs1(0), .imm(-1)),
|
|
asm_instr(.op(OP_ADDI), .rd(2), .rs1(0), .imm(1)),
|
|
asm_instr(.op(OP_SLL), .rd(1), .rs1(1), .rs2(2)),
|
|
EBREAK_WORD
|
|
};
|
|
```
|
|
|
|
**Expected result:**
|
|
|
|
| Register or memory word | Expected value | Calculation or explanation |
|
|
| ----------------------- | -------------- | ------------------------------ |
|
|
| `x1` | `32'hFFFFFFFE` | 0xFFFFFFFF << 0x1 = 0xFFFFFFFE |
|
|
|
|
**Pass criteria:** 3 cycle operation
|
|
|
|
**Final result:** <!-- Complete in testplan_final.md: pass/fail and useful log or waveform reference. -->
|
|
|
|
### 1.14 — `srl one`
|
|
|
|
**Functionality:** srl with one, causing a shift once to the right
|
|
|
|
**Initial state:**
|
|
|
|
- Registers: x1 = 0xFFFFFFFF, x2 = 1
|
|
- Data memory: none
|
|
- Other setup: none
|
|
|
|
**Program:**
|
|
|
|
<!-- Use the same representation that will be placed in run_member_directed_tests(). -->
|
|
|
|
```systemverilog
|
|
prog = '{
|
|
// asm_instr(.op(...), .rd(...), .rs1(...), .rs2(...), .imm(...)),
|
|
asm_instr(.op(OP_ADDI), .rd(1), .rs1(0), .imm(-1)),
|
|
asm_instr(.op(OP_ADDI), .rd(2), .rs1(0), .imm(1)),
|
|
asm_instr(.op(OP_SRL), .rd(1), .rs1(1), .rs2(2)),
|
|
EBREAK_WORD
|
|
};
|
|
```
|
|
|
|
**Expected result:**
|
|
|
|
| Register or memory word | Expected value | Calculation or explanation |
|
|
| ----------------------- | -------------- | ----------------------------- |
|
|
| `x1` | `32'h7FFFFFFF` | 0xFFFFFFFF >> 0x1 = 0x7FFFFFFF |
|
|
|
|
**Pass criteria:** 3 cycle operation
|
|
|
|
**Final result:** <!-- Complete in testplan_final.md: pass/fail and useful log or waveform reference. -->
|
|
|
|
### 1.15 — `sll typical`
|
|
|
|
**Functionality:** sll with a shift greater than 1 and less than 2^5
|
|
|
|
**Initial state:**
|
|
|
|
- Registers: x1 = 0xFFFFFFFF, x2 = 0x4
|
|
- Data memory: none
|
|
- Other setup: none
|
|
|
|
**Program:**
|
|
|
|
<!-- Use the same representation that will be placed in run_member_directed_tests(). -->
|
|
|
|
```systemverilog
|
|
prog = '{
|
|
// asm_instr(.op(...), .rd(...), .rs1(...), .rs2(...), .imm(...)),
|
|
asm_instr(.op(OP_ADDI), .rd(1), .rs1(0), .imm(-1)),
|
|
asm_instr(.op(OP_ADDI), .rd(2), .rs1(0), .imm(4)),
|
|
asm_instr(.op(OP_SLL), .rd(1), .rs1(1), .rs2(2)),
|
|
EBREAK_WORD
|
|
};
|
|
```
|
|
|
|
**Expected result:**
|
|
|
|
| Register or memory word | Expected value | Calculation or explanation |
|
|
| ----------------------- | -------------- | ------------------------------ |
|
|
| `x1` | `32'hFFFFFFF0` | 0xFFFFFFFF << 0x4 = 0xFFFFFFF0 |
|
|
|
|
**Pass criteria:** 3 cycle operation
|
|
|
|
**Final result:** <!-- Complete in testplan_final.md: pass/fail and useful log or waveform reference. -->
|
|
|
|
### 1.16 — `srl typical`
|
|
|
|
**Functionality:** srl with a shift greater than 1 and less than 2^5
|
|
|
|
**Initial state:**
|
|
|
|
- Registers: x1 = 0xFFFFFFFF, x2 = 0x4
|
|
- Data memory: none
|
|
- Other setup: none
|
|
|
|
**Program:**
|
|
|
|
<!-- Use the same representation that will be placed in run_member_directed_tests(). -->
|
|
|
|
```systemverilog
|
|
prog = '{
|
|
// asm_instr(.op(...), .rd(...), .rs1(...), .rs2(...), .imm(...)),
|
|
asm_instr(.op(OP_ADDI), .rd(1), .rs1(0), .imm(-1)),
|
|
asm_instr(.op(OP_ADDI), .rd(2), .rs1(0), .imm(4)),
|
|
asm_instr(.op(OP_SRL), .rd(1), .rs1(1), .rs2(2)),
|
|
EBREAK_WORD
|
|
};
|
|
```
|
|
|
|
**Expected result:**
|
|
|
|
| Register or memory word | Expected value | Calculation or explanation |
|
|
| ----------------------- | -------------- | ------------------------------ |
|
|
| `x1` | `32'h0FFFFFFF` | 0xFFFFFFFF >> 0x4 = 0x0FFFFFFF |
|
|
|
|
**Pass criteria:** 3 cycle operation
|
|
|
|
**Final result:** <!-- Complete in testplan_final.md: pass/fail and useful log or waveform reference. -->
|
|
|
|
### 1.17 — `lw zero offset`
|
|
|
|
**Functionality:** lw with zero offset, loading in the register rs1
|
|
|
|
**Initial state:**
|
|
|
|
- Registers: none
|
|
- Data memory: dmem[0] = 0xFFFFFFFF
|
|
- Other setup: none
|
|
|
|
**Program:**
|
|
|
|
<!-- Use the same representation that will be placed in run_member_directed_tests(). -->
|
|
|
|
```systemverilog
|
|
prog = '{
|
|
// asm_instr(.op(...), .rd(...), .rs1(...), .rs2(...), .imm(...)),
|
|
asm_instr(.op(OP_LW), .rd(1), .rs1(0), .imm(0)),
|
|
EBREAK_WORD
|
|
};
|
|
```
|
|
|
|
**Expected result:**
|
|
|
|
| Register or memory word | Expected value | Calculation or explanation |
|
|
| ----------------------- | -------------- | -------------------------- |
|
|
| `x1` | `32'hFFFFFFFF` | x1 = M[0] => 0xFFFFFFFF |
|
|
|
|
**Pass criteria:** 2 cycle operation
|
|
|
|
**Final result:** <!-- Complete in testplan_final.md: pass/fail and useful log or waveform reference. -->
|
|
|
|
### 1.18 — `sw zero offset`
|
|
|
|
**Functionality:** sw with zero offset, storing in memory addr of rs1
|
|
|
|
**Initial state:**
|
|
|
|
- Registers: x1 = 0xFFFFFFFF
|
|
- Data memory: none
|
|
- Other setup: none
|
|
|
|
**Program:**
|
|
|
|
<!-- Use the same representation that will be placed in run_member_directed_tests(). -->
|
|
|
|
```systemverilog
|
|
prog = '{
|
|
// asm_instr(.op(...), .rd(...), .rs1(...), .rs2(...), .imm(...)),
|
|
asm_instr(.op(OP_ADDI), .rd(1), .rs1(0), .imm(-1)),
|
|
asm_instr(.op(OP_SW), .rs1(0), .rs2(1), .imm(0)),
|
|
EBREAK_WORD
|
|
};
|
|
```
|
|
|
|
**Expected result:**
|
|
|
|
| Register or memory word | Expected value | Calculation or explanation |
|
|
| ----------------------- | -------------- | -------------------------- |
|
|
| `dmem[0]` | `32'hFFFFFFFF` | M[0] = x1 => 0xFFFFFFFF |
|
|
|
|
**Pass criteria:** 2 cycle operation
|
|
|
|
**Final result:** <!-- Complete in testplan_final.md: pass/fail and useful log or waveform reference. -->
|
|
|
|
### 1.19 — `lw positive`
|
|
|
|
**Functionality:** lw with a positive offset
|
|
|
|
**Initial state:**
|
|
|
|
- Registers: none
|
|
- Data memory: dmem[1] = 0xFFFFFFFF
|
|
- Other setup: none
|
|
|
|
**Program:**
|
|
|
|
<!-- Use the same representation that will be placed in run_member_directed_tests(). -->
|
|
|
|
```systemverilog
|
|
prog = '{
|
|
// asm_instr(.op(...), .rd(...), .rs1(...), .rs2(...), .imm(...)),
|
|
asm_instr(.op(OP_LW), .rd(1), .rs1(0), .imm(4)),
|
|
EBREAK_WORD
|
|
};
|
|
```
|
|
|
|
**Expected result:**
|
|
|
|
| Register or memory word | Expected value | Calculation or explanation |
|
|
| ----------------------- | -------------- | -------------------------- |
|
|
| `x1` | `32'hFFFFFFFF` | x1 = dmem[1] => 0xFFFFFFFF |
|
|
|
|
**Pass criteria:** 2 cycle operation
|
|
|
|
**Final result:** <!-- Complete in testplan_final.md: pass/fail and useful log or waveform reference. -->
|
|
|
|
### 1.20 — `sw positive`
|
|
|
|
**Functionality:** sw with a positive offset
|
|
|
|
**Initial state:**
|
|
|
|
- Registers: x1 = 0xFFFFFFFF
|
|
- Data memory: none
|
|
- Other setup: none
|
|
|
|
**Program:**
|
|
|
|
<!-- Use the same representation that will be placed in run_member_directed_tests(). -->
|
|
|
|
```systemverilog
|
|
prog = '{
|
|
// asm_instr(.op(...), .rd(...), .rs1(...), .rs2(...), .imm(...)),
|
|
asm_instr(.op(OP_ADDI), .rd(1), .rs1(0), .imm(-1)),
|
|
asm_instr(.op(OP_SW), .rs1(0), .rs2(1), .imm(4)),
|
|
EBREAK_WORD
|
|
};
|
|
```
|
|
|
|
**Expected result:**
|
|
|
|
| Register or memory word | Expected value | Calculation or explanation |
|
|
| ----------------------- | -------------- | -------------------------- |
|
|
| `dmem[1]` | `32'hFFFFFFFF` | dmem[1] = x1 => 0xFFFFFFFF |
|
|
|
|
**Pass criteria:** 2 cycle operation
|
|
|
|
**Final result:** <!-- Complete in testplan_final.md: pass/fail and useful log or waveform reference. -->
|
|
|
|
### 1.21 — `lw negative`
|
|
|
|
**Functionality:** lw with a negative offset
|
|
|
|
**Initial state:**
|
|
|
|
- Registers: none
|
|
- Data memory: dmem[1023] = 0xFFFFFFFF
|
|
- Other setup: none
|
|
|
|
**Program:**
|
|
|
|
<!-- Use the same representation that will be placed in run_member_directed_tests(). -->
|
|
|
|
```systemverilog
|
|
prog = '{
|
|
// asm_instr(.op(...), .rd(...), .rs1(...), .rs2(...), .imm(...)),
|
|
asm_instr(.op(OP_LW), .rd(1), .rs1(0), .imm(-1)),
|
|
EBREAK_WORD
|
|
};
|
|
```
|
|
|
|
**Expected result:**
|
|
|
|
| Register or memory word | Expected value | Calculation or explanation |
|
|
| ----------------------- | -------------- | ----------------------------- |
|
|
| `x1` | `32'hFFFFFFFF` | x1 = dmem[1023] => 0xFFFFFFFF |
|
|
|
|
**Pass criteria:** 2 cycle operation
|
|
|
|
**Final result:** <!-- Complete in testplan_final.md: pass/fail and useful log or waveform reference. -->
|
|
|
|
### 1.22 — `sw negative`
|
|
|
|
**Functionality:** sw with a negative offset
|
|
|
|
**Initial state:**
|
|
|
|
- Registers: x1 = 0xFFFFFFFF
|
|
- Data memory: none
|
|
- Other setup: none
|
|
|
|
**Program:**
|
|
|
|
<!-- Use the same representation that will be placed in run_member_directed_tests(). -->
|
|
|
|
```systemverilog
|
|
prog = '{
|
|
// asm_instr(.op(...), .rd(...), .rs1(...), .rs2(...), .imm(...)),
|
|
asm_instr(.op(OP_ADDI), .rd(1), .rs1(0), .imm(-1)),
|
|
asm_instr(.op(OP_SW), .rs1(0), .rs2(1), .imm(-1)),
|
|
EBREAK_WORD
|
|
};
|
|
```
|
|
|
|
**Expected result:**
|
|
|
|
| Register or memory word | Expected value | Calculation or explanation |
|
|
| ----------------------- | -------------- | ----------------------------- |
|
|
| `dmem[1023]` | `32'hFFFFFFFF` | dmem[1023] = x1 => 0xFFFFFFFF |
|
|
|
|
**Pass criteria:** 2 cycle operation
|
|
|
|
**Final result:** <!-- Complete in testplan_final.md: pass/fail and useful log or waveform reference. -->
|
|
|
|
### 1.23 — `lw x0`
|
|
|
|
**Functionality:** attempt to lw into x0 register
|
|
|
|
**Initial state:**
|
|
|
|
- Registers: none
|
|
- Data memory: dmem[0] = 0xFFFFFFFF
|
|
- Other setup: none
|
|
|
|
**Program:**
|
|
|
|
<!-- Use the same representation that will be placed in run_member_directed_tests(). -->
|
|
|
|
```systemverilog
|
|
prog = '{
|
|
// asm_instr(.op(...), .rd(...), .rs1(...), .rs2(...), .imm(...)),
|
|
asm_instr(.op(OP_LW), .rd(0), .rs1(0), .imm(0)),
|
|
EBREAK_WORD
|
|
};
|
|
```
|
|
|
|
**Expected result:**
|
|
|
|
| Register or memory word | Expected value | Calculation or explanation |
|
|
| ----------------------- | -------------- | -------------------------- |
|
|
| `x0` | `32'h0` | x0 is to always remain 0 |
|
|
|
|
**Pass criteria:** 2 cycle operation
|
|
|
|
**Final result:** <!-- Complete in testplan_final.md: pass/fail and useful log or waveform reference. -->
|
|
|
|
### 1.24 — `beq x0`
|
|
|
|
**Functionality:** beq with both sources as x0
|
|
|
|
**Initial state:**
|
|
|
|
- Registers: none
|
|
- Data memory: none
|
|
- Other setup: none
|
|
|
|
**Program:**
|
|
|
|
<!-- Use the same representation that will be placed in run_member_directed_tests(). -->
|
|
|
|
```systemverilog
|
|
prog = '{
|
|
// asm_instr(.op(...), .rd(...), .rs1(...), .rs2(...), .imm(...)),
|
|
asm_instr(.op(OP_BEQ), .rs1(0), .rs2(0), .imm(8)),
|
|
asm_instr(.op(OP_ADDI), .rd(1), .rs1(0), .imm(1)),
|
|
asm_instr(.op(OP_ADDI), .rd(1), .rs1(0), .imm(2)),
|
|
EBREAK_WORD
|
|
};
|
|
```
|
|
|
|
**Expected result:**
|
|
|
|
| Register or memory word | Expected value | Calculation or explanation |
|
|
| ----------------------- | -------------- | ------------------------------------------- |
|
|
| `x1` | `32'h2` | skip ADDI x1, x0, 1, and run ADDI x1, x0, 2 |
|
|
|
|
**Pass criteria:** 2 cycle operation
|
|
|
|
**Final result:** <!-- Complete in testplan_final.md: pass/fail and useful log or waveform reference. -->
|
|
|
|
### 1.25 — `beq not taken`
|
|
|
|
**Functionality:** beq on two non-equal registers
|
|
|
|
**Initial state:**
|
|
|
|
- Registers: x1 = 0xFFFFFFFF
|
|
- Data memory: none
|
|
- Other setup: none
|
|
|
|
**Program:**
|
|
|
|
<!-- Use the same representation that will be placed in run_member_directed_tests(). -->
|
|
|
|
```systemverilog
|
|
prog = '{
|
|
// asm_instr(.op(...), .rd(...), .rs1(...), .rs2(...), .imm(...)),
|
|
asm_instr(.op(OP_ADDI), .rd(1), .rs1(0), .imm(-1)),
|
|
asm_instr(.op(OP_BEQ), .rs1(0), .rs2(1), .imm(8)),
|
|
asm_instr(.op(OP_ADDI), .rd(2), .rs1(0), .imm(-1)),
|
|
EBREAK_WORD
|
|
};
|
|
```
|
|
|
|
**Expected result:**
|
|
|
|
| Register or memory word | Expected value | Calculation or explanation |
|
|
| ----------------------- | -------------- | ---------------------------------------------- |
|
|
| `x2` | `32'hFFFFFFFF` | do not skip to EBREAK, and run ADDI x2, x0, -1 |
|
|
|
|
**Pass criteria:** 3 cycle operation
|
|
|
|
**Final result:** <!-- Complete in testplan_final.md: pass/fail and useful log or waveform reference. -->
|
|
|
|
### 1.26 — `beq typical`
|
|
|
|
**Functionality:** beq on two equal registers that are not x0
|
|
|
|
**Initial state:**
|
|
|
|
- Registers: x1 = 0xFFFFFFFF, x2 = 0xFFFFFFFF
|
|
- Data memory: none
|
|
- Other setup: none
|
|
|
|
**Program:**
|
|
|
|
<!-- Use the same representation that will be placed in run_member_directed_tests(). -->
|
|
|
|
```systemverilog
|
|
prog = '{
|
|
// asm_instr(.op(...), .rd(...), .rs1(...), .rs2(...), .imm(...)),
|
|
asm_instr(.op(OP_ADDI), .rd(1), .rs1(0), .imm(-1)),
|
|
asm_instr(.op(OP_ADDI), .rd(2), .rs1(0), .imm(-1)),
|
|
asm_instr(.op(OP_BEQ), .rs1(1), .rs2(2), .imm(8)),
|
|
asm_instr(.op(OP_ADDI), .rd(3), .rs1(0), .imm(1)),
|
|
asm_instr(.op(OP_ADDI), .rd(3), .rs1(0), .imm(2)),
|
|
EBREAK_WORD
|
|
};
|
|
```
|
|
|
|
**Expected result:**
|
|
|
|
| Register or memory word | Expected value | Calculation or explanation |
|
|
| ----------------------- | -------------- | ------------------------------------------- |
|
|
| `x3` | `32'h2` | skip ADDI x3, x0, 1, and run ADDI x3, x0, 2 |
|
|
|
|
**Pass criteria:** 4 cycle operation
|
|
|
|
**Final result:** <!-- Complete in testplan_final.md: pass/fail and useful log or waveform reference. -->
|
|
|
|
### 1.27 — `ebreak immediately`
|
|
|
|
**Functionality:** ebreak as first instruction, subsequent instructions not run
|
|
|
|
**Initial state:**
|
|
|
|
- Registers: none
|
|
- Data memory: none
|
|
- Other setup: none
|
|
|
|
**Program:**
|
|
|
|
<!-- Use the same representation that will be placed in run_member_directed_tests(). -->
|
|
|
|
```systemverilog
|
|
prog = '{
|
|
// asm_instr(.op(...), .rd(...), .rs1(...), .rs2(...), .imm(...)),
|
|
EBREAK_WORD,
|
|
asm_instr(.op(OP_ADDI), .rd(1), .rs1(0), .imm(-1))
|
|
};
|
|
```
|
|
|
|
**Expected result:**
|
|
|
|
| Register or memory word | Expected value | Calculation or explanation |
|
|
| ----------------------- | -------------- | ------------------------------ |
|
|
| `x1` | `32'h0` | ebreak before ADDI instruction |
|
|
|
|
**Pass criteria:** ebreak takes one cycle, other instructions not run
|
|
|
|
**Final result:** <!-- Complete in testplan_final.md: pass/fail and useful log or waveform reference. -->
|
|
|
|
## 2. Constrained-random tests
|
|
|
|
### Instruction constraints
|
|
|
|
<!--
|
|
Explain the provided constraints, then record how the partial and open
|
|
constraints are completed. State what each constraint permits, excludes, or
|
|
biases and why the resulting programs remain useful and terminating.
|
|
-->
|
|
|
|
| Constraint | Provided, partial, or open | Behavior and purpose | Final implementation summary |
|
|
| --------------------- | -------------------------- | ----------------------------------------------- | ----------------------------------------------- |
|
|
| `c_opcode` | Provided | use only opcodes implemented | No member change |
|
|
| `c_reg_bias` | Provided | encourage more reg-reg collisions, test x0 r/w | No member change |
|
|
| `c_imm_range` | Partial | use only immediates that fit into instruction | separate imm_range for I/S and B types |
|
|
| `c_mem_align` | Open | force word immediates to be multiples of 4 | mask/discard 2 LSBs for lw/sw |
|
|
| `c_imm_unused` | Provided | set imm to zero if not used in instr | No member change |
|
|
| `c_branch_target` | Partial | keep the target within the program mem | % 4, ≥ 4, <prog len |
|
|
| `c_no_branch_at_end` | Provided | prevent branching at the end of the program | No member change |
|
|
| `c_branch_taken_bias` | Open | bias rs1/rs2 to being equal values to eachother | weight rs1/rs2 values to encourage equal values |
|
|
|
|
### External-port constraints
|
|
|
|
| Constraint | Provided, partial, or open | Behavior and purpose | Final implementation summary |
|
|
| ----------------- | -------------------------- | ----------------------------------------- | --------------------------------- |
|
|
| `c_align` | Provided | word align instr | No member change |
|
|
| `c_valid_window` | Partial | ensure addr is inside register file | restrict to 32 entries |
|
|
| `c_reg_read_only` | Provided | do not write to reg via port | No member change |
|
|
| `c_data_corners` | Open | bias towards specific data values to test | all 1s, all 0s, checkerboard, etc |
|
|
|
|
### Random-program test
|
|
|
|
| Item | Plan |
|
|
| ----------------------------------- | ----------------------------------------------------------- |
|
|
| Number of programs per seed | 50 |
|
|
| Program-length range | 2 ≤ len ≤ 50 |
|
|
| Information logged for reproduction | Numeric `SVSEED`, iteration, and complete generated program |
|
|
|
|
**Implementation outline:**
|
|
|
|
```systemverilog
|
|
// Write the intended loop and lifecycle using seqr.gen_program(...).
|
|
int min_len = 2;
|
|
int max_len = 50;
|
|
int random_progs = 50;
|
|
int max_cycles = 2000;
|
|
int dmem_words = 16;
|
|
|
|
for (int i = 0; i < random_progs; i++) begin
|
|
int len = $urandom_range(min_len, max_len);
|
|
string name = $sformatf("random_gen_%0d_len_%0d", i, len);
|
|
sb.set_test(name);
|
|
|
|
drv.reset_task();
|
|
seqr.gen_program(len);
|
|
seqr.wait_for_empty();
|
|
repeat (2) @(cpu_if.cb);
|
|
drv.run_program(max_cycles);
|
|
|
|
if (drv.last_run_completed) begin
|
|
readback(2, REG_COUNT);
|
|
readback(1, dmem_words);
|
|
end else begin
|
|
$display($stime, " TB: Skipping %s readback after CPU timeout\n", name);
|
|
drv.reset_task();
|
|
end
|
|
end
|
|
```
|
|
|
|
## 3. Assertions
|
|
|
|
<!--
|
|
Plan at least two assertions in addition to the supplied example. Write the
|
|
timing rule in English first. In the final plan, include the exact SVA and
|
|
evidence from a temporary violation proving that the assertion can fire.
|
|
-->
|
|
|
|
### Assertion summary
|
|
|
|
| Assertion ID/name | Behavior checked | When it is sampled/disabled | Activating test |
|
|
| -------------------- | ------------------------- | --------------------------- | ------------------ |
|
|
| 3.1 / `X0_REMAINS_0` | x0 = 0 | posedge clk | lw_x0 |
|
|
| 3.2 / `HALT_PULSE` | halt pulses high then low | after ebreak | ebreak_immediately |
|
|
|
|
### 3.1 — `X0_REMAINS_0`
|
|
|
|
**Timing requirement in words:** on every clock pulse, check that x0 is 0
|
|
|
|
```systemverilog
|
|
X0_REMAINS_0:
|
|
assert property (@(posedge clk) disable iff (rst)
|
|
dut.register_crossbar[0] == 32'b0)
|
|
else assertion_fail("x0 is nonzero");
|
|
```
|
|
|
|
**Evidence that it detects a violation:** <!-- Temporary change, failing log/waveform, and confirmation after reverting it. -->
|
|
|
|
### 3.2 — `HALT_PULSE`
|
|
|
|
**Timing requirement in words:** halt pulses after ebreak
|
|
|
|
```systemverilog
|
|
HALT_PULSE:
|
|
assert property (@(posedge clk) disable iff (rst)
|
|
cpu_if.cpu_halted |=> !cpu_if.cpu_halted)
|
|
else assertion_fail("halt did not pulse correctly");
|
|
```
|
|
|
|
**Evidence that it detects a violation:**
|
|
|
|
## 4. Encrypted CPU Bug Hunt
|
|
|
|
### Random discovery
|
|
|
|
| Field | Evidence |
|
|
| ------------------------ | ----------------------------- |
|
|
| Discovery command | `make bug_hunt SEED=random` |
|
|
| Numeric `SVSEED` | |
|
|
| Failing iteration | |
|
|
| First failure message | |
|
|
| Reproduction command | `make bug_hunt SEED=________` |
|
|
| Reproduces consistently? | Yes / No |
|
|
|
|
**Original failing program:**
|
|
|
|
```systemverilog
|
|
prog = '{
|
|
// Paste original generated sequence
|
|
EBREAK_WORD
|
|
};
|
|
```
|
|
|
|
### Expected vs. actual
|
|
|
|
| Instruction / event | Expected | Actual | Cycle/time |
|
|
| ------------------- | -------- | ------ | ---------- |
|
|
| | | | |
|
|
|
|
**First architectural divergence:**
|
|
|
|
<!-- State the first register, memory, or control-flow result that becomes incorrect. -->
|
|
|
|
### Minimization
|
|
|
|
**Minimized reproducer:**
|
|
|
|
```systemverilog
|
|
prog = '{
|
|
// Smallest sequence that still fails
|
|
EBREAK_WORD
|
|
};
|
|
```
|
|
|
|
### Waveform evidence
|
|
|
|
Include a screenshot showing the offending instruction and the first incorrect architectural result.
|
|
|
|
### Conclusion
|
|
|
|
**Trigger:**
|
|
|
|
<!-- Smallest condition that causes the failure. -->
|
|
|
|
**Expected behavior:**
|
|
|
|
<!-- ISA-correct behavior. -->
|
|
|
|
**Observed behavior:**
|
|
|
|
<!-- What the encrypted CPU does instead. -->
|
|
|
|
**Behavioral characterization:**
|
|
|
|
<!-- One precise sentence. Do not speculate about hidden RTL. -->
|
|
|