Abstract Functions (Oracle-based Verification)
Abstract functions are one of three approaches used to fill gaps left in generated Verilog at the interfaces between ISA-specified partitions and other parts of a processor design (such as the memory system, floating-point units, or exception/address-translation logic) when verifying ARM processors with ISA-Formal. Where the generated Verilog for the "Instruction Set Architecture" partition omits functions at call boundaries, abstract functions provide an oracle-based strategy for the remaining unfilled interfaces (cfd57488).
Motivation
When the ISA specification is partitioned along function-call boundaries into parts such as "Instruction Set Architecture," "Floating Point," "Exception," and "Address Translation," Verilog is only generated for the ISA part. Hand-written shims of a few lines bridge the other interfaces, but this leaves parts of the processor un-checked by ISA-Formal. The authors therefore track which parts of the processor are not checked by ISA-Formal and ensure that an alternative verification technique covers those parts. Abstract functions are one such alternative, complementing interface properties and subset behaviour checking (cfd57488).
Mechanism
The technique works by adding logic that tracks the inputs and outputs from some functional unit in the processor. The processor itself is then used as an oracle:
- Auxiliary logic observes the actual inputs supplied to a functional unit during simulation and records the corresponding outputs produced by that unit.
- If the inputs of a function in the architectural specification match the actual inputs observed for a functional unit in the processor, the recorded oracle output is used as the expected value for that function in the specification.
Because the behaviour of the chosen unit is trusted by construction, abstract functions cannot detect bugs inside the unit itself. However, they can detect bugs in the surrounding control and forwarding logic that route values into and out of the unit, since mismatches between the recorded oracle behaviour and the architectural expectation will surface during checking (cfd57488).
Relationship to the Other Interface Strategies
- Interface properties are used when an existing interface specification is already strong enough — for example, the memory system, where an architectural-to-microarchitectural translator of requests and responses suffices (cfd57488).
- Subset behaviour checking is used when the full behaviour of a unit is too complex to specify but a restricted subset is tractable — for example, restricting floating-point inputs to ±{0, 1, ∞, S-NaN, Q-NaN}. A separate signal indicates whether the inputs are in the supported subset so that this restriction only affects checks of values written to floating-point registers and not other ISA-Formal checks (condition flags, exceptions, memory accesses, register writes) (cfd57488).
- Abstract functions are the fallback used when neither of the above is sufficient, leveraging the processor itself as the oracle (cfd57488).
Trade-offs
- Strengths: Catches errors in control logic and forwarding around the unit; does not require a complete formal specification of the unit.
- Limitations: Cannot detect bugs inside the trusted functional unit, so it must be paired with other verification techniques that cover the unit itself.
Use in Context
In the broader end-to-end verification effort described in the CAV 2016 paper, abstract functions are part of the toolbox that allows ISA-Formal to be applied to realistic, partitioned ARM processor designs — including out-of-order completing cores, where constructing an accurate post-state is complicated by instructions such as loads being split into multiple micro-ops that complete independently. The paper proposes taking a snapshot of the pre-state when such an instruction retires and updating the snapshot as each micro-op completes (cfd57488). This style of state tracking is conceptually aligned with the input/output observation performed by abstract functions.