Skip to content

Formal Platform Integration #505

Open
@cr1901

Description

@cr1901

Right now, the scope of formal is the following, copied directly from IRC:

(11:56:43 AM) whitequark: the entire scope of formal verification in nmigen at the moment is "it can generate verilog or rtlil with assert/assume statements"
(11:57:10 AM) whitequark: i do not, at the moment, provide anything beyond that, and doing it requires thinking first and coding second

This is a pre-RFC to discuss what other functionality we'd want out of formal integration. Specifically, I'm assuming an end goal will be something along the lines of:

Given a test harness w/ assert/assume and a design w/ assert/assume statements, running a formal verification flow of an Elaboratable in nmigen will be of comparable complexity to synthesizing and programming a bitstream via nmigen.build.plat.Platform.build(). Formal (in symbiyosys, either Bounded Model Check (BMC) and/or k-induction)

To start, I can think of at least three things I want:

  • Minimal hassle to invoke symbiyosys that "does the right thing" on a Fragment or Module (Elaboratable). See above.

  • Per IRC, a formal Platform is probably desirable. Current approach is to inject platform=formal into rtlil/verilog.convert() or similar instead of using nmigen.build. I have some thoughts here:

    • I think it's reasonable that rtlil/verilog.convert() on it's own either emits or excludes asserts/assumes via an option.
    • My gut feeling tells that building for a platform which has assertions and synthesizing a bitstream should be mutually exclusive because synth and formal are meant to do two different tasks. Failing that:
      • I would still like the ability to easily clean up formal output artifacts without them intermingling with synthesis output artifacts; for instance, invoking via sby -d sby_dir formal.sby.
      • Input artifact mingling should also be kept to a minimum. A minimum set of inputs affected by emitting for both formal ans synthesis might be: the sby file, one set of .il/v input for synthesis w/o asserts/assumes, and another set of .il/v for sby.
  • Multiclock support. This one is tougher, it's easy to make a design w/ multiclock fail because the solver will hold one of the clocks steady to prevent forward progress (when a constraint violation is imminent) until n timesteps have elapsed. One way around this is to utilize the $global_clock clock and do something like this for each clock to force each clock to eventually tick:

    reg last_clk = 0;
    
    always @($global_clock) begin
          last_clk <= clk;
          assume(last_clk != clk);
    end
    

    When we discussed $global_clock last year, we agreed to not expose $global_clock within nmigen, but we couldn't come up with a good set of constraints that should be autogenerated for formal testbenches with multiple clocks to force forward progress (I think "all n clocks must have ticked at least once in the past n cycles" might work?). I think we should review this.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions