Skip to content

Write symbolic value at symbolic index #151

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

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package/version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.1.112
0.1.113
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "hatchling.build"

[project]
name = "kriscv"
version = "0.1.112"
version = "0.1.113"
description = "K tooling for the RISC-V architecture"
readme = "README.md"
requires-python = "~=3.10"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,54 @@ For symbolic execution, we need to tackle the patterns of `#bytes(B +Bytes _) _`
requires I >=Int lengthBytes(B) [simplification(45), preserves-definedness]
```

## writeBytes

If the write index is concrete, we can directly call `writeBytesBF` or `writeBytesEF`.

```k
rule writeBytes(I, V, NUM, BF:SparseBytesBF) => writeBytesBF(I, V, NUM, BF) [simplification(45), concrete(I)]
rule writeBytes(I, V, NUM, EF:SparseBytesEF) => writeBytesEF(I, V, NUM, EF) [simplification(45), concrete(I)]
```

If the write index is symbolic, we use `#WB` to wrap the write operation. Unlike `writeBytes`, `#WB` contains a boolean value to determine whether the write operation has been completed. `true` means completed, `false` means not completed.

```k
syntax SparseBytes ::= #WB(Bool, Int, Int, Int, SparseBytes) [function, total]
rule #WB(_, I, V, NUM, B:SparseBytes) => writeBytes(I, V, NUM, B) [concrete]
rule writeBytes(I, V, NUM, B:SparseBytes) => #WB(false, I, V, NUM, B) [simplification]
```

**Termination Control**: The boolean flag ensures that symbolic write operations eventually terminate by transitioning from `false` to `true` state, at which point concrete write functions can be applied when the index becomes concrete.

```k
rule #WB(false, I, V, NUM, BF:SparseBytesBF) => #WB(true, I, V, NUM, BF) [simplification]
rule #WB(false, I, V, NUM, EF:SparseBytesEF) => #WB(true, I, V, NUM, EF) [simplification]
rule #WB(true, I, V, NUM, BF:SparseBytesBF) => writeBytesBF(I, V, NUM, BF) [simplification, concrete(I)]
rule #WB(true, I, V, NUM, EF:SparseBytesEF) => writeBytesEF(I, V, NUM, EF) [simplification, concrete(I)]
```

**Reordering for Optimization**: When multiple `#WB` operations are nested, the rules bring incomplete `#WB` operations (with `false` flag) to the terminal position, allowing them to traverse and find all possible merge opportunities.

```k
rule #WB(false, I0, V0, NUM0, #WB(true, I1, V1, NUM1, B:SparseBytes)) => #WB(true, I1, V1, NUM1, #WB(false, I0, V0, NUM0, B)) [simplification]
requires I0 =/=Int I1
```

The following rule tackles a special case when indices are the same but `NUM0 < NUM1`: in this situation, merging would introduce additional terms, so the operation is directly marked as completed to avoid complexity.

```k
rule #WB(false, I0, V0, NUM0, #WB(true, I1, V1, NUM1, B:SparseBytes)) => #WB(true, I0, V0, NUM0, #WB(true, I1, V1, NUM1, B))
requires I0 ==Int I1 [simplification]
```

**Write Consolidation**: When multiple write operations target the same symbolic index with equal byte counts (`NUM0 == NUM1`), the rules merge them by eliminating the older write operation. When the new write has fewer bytes than the existing one (`NUM1 < NUM0`), the smaller write is also eliminated to maintain simplicity.

```k
rule #WB(false, I0, V0, NUM0, #WB(_, I1, _, NUM1, B:SparseBytes)) => #WB(false, I0, V0, NUM0, B)
requires NUM0 ==Int NUM1 andBool I0 ==Int I1 [simplification(45)]
rule #WB(false, I0, V0, NUM0, #WB(_, I1, _, NUM1, B:SparseBytes)) => #WB(false, I0, V0, NUM0, B)
requires NUM1 <Int NUM0 andBool I0 ==Int I1 [simplification(45)]
```

## writeByteBF

Expand Down
4 changes: 2 additions & 2 deletions src/kriscv/kdist/riscv-semantics/sparse-bytes.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,8 @@ We provide helpers to prepend either data or an empty region to an existing `Spa
| writeBytesEF(Int, Int, Int, SparseBytesEF) [function, total]
| writeBytesBF(Int, Int, Int, SparseBytesBF) [function, total]

rule writeBytes(I, V, NUM, BF:SparseBytesBF) => writeBytesBF(I, V, NUM, BF)
rule writeBytes(I, V, NUM, EF:SparseBytesEF) => writeBytesEF(I, V, NUM, EF)
rule writeBytes(I, V, NUM, BF:SparseBytesBF) => writeBytesBF(I, V, NUM, BF) [concrete]
rule writeBytes(I, V, NUM, EF:SparseBytesEF) => writeBytesEF(I, V, NUM, EF) [concrete]

rule writeBytesEF(I, _, _ , _ ) => .SparseBytes requires I <Int 0 // error case for totality
rule writeBytesEF(I, V, NUM, .SparseBytes) => prependEmpty(I, #bytes(Int2Bytes(NUM, V, LE)) .SparseBytes) requires I >=Int 0
Expand Down
26 changes: 26 additions & 0 deletions src/tests/integration/test-data/specs/store-symbolic-index-value.k
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
module STORE-SYMBOLIC-INDEX-VALUE
imports RISCV

claim [id]:
<instrs> #CHECK_HALT => #HALT </instrs>
<regs>
.Map
</regs>
<pc> 0 </pc>
<mem>
storeBytes(0 , V6, 4,
storeBytes(I2, V5, 4,
storeBytes(I1, V4, 2,
storeBytes(I0, V3, 4,
storeBytes(I2, V2, 2,
storeBytes(I1, V1, 4,
storeBytes(I0, V0, 4, #bytes ( b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" ) .SparseBytes)))))))
=> // No way to simplify this without any information about the index. Just eliminate the writes on the same index.
#WB(true, I1, V4, 2,
#WB(true, I1, V1, 4,
#WB(true, I0, V3, 4,
#WB(true, I2, V5, 4,
#bytes (Int2Bytes(4, V6, LE) +Bytes b"\x00\x00\x00\x00\x00\x00\x00\x00") .SparseBytes))))
</mem>
<haltCond> ADDRESS ( 0 ) </haltCond>
endmodule
2 changes: 1 addition & 1 deletion uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading