Compare commits
2 Commits
cf483decad
...
7b46ae5e87
| Author | SHA1 | Date | |
|---|---|---|---|
| 7b46ae5e87 | |||
| 8289b0d090 |
91
cores/wb/check_formal.sh
Executable file
91
cores/wb/check_formal.sh
Executable file
@@ -0,0 +1,91 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Add or remove cores here. Each entry should be a full FuseSoC VLNV.
|
||||||
|
CORES="
|
||||||
|
joppeb:wb:wb_mem32
|
||||||
|
joppeb:wb:wb_gpio
|
||||||
|
joppeb:wb:wb_gpio_banks
|
||||||
|
joppeb:wb:jtag_wb_bridge
|
||||||
|
joppeb:wb:wb_timer
|
||||||
|
"
|
||||||
|
|
||||||
|
# Add or remove formal tasks here.
|
||||||
|
TASKS="
|
||||||
|
bmc
|
||||||
|
cover
|
||||||
|
prove
|
||||||
|
"
|
||||||
|
|
||||||
|
total=0
|
||||||
|
passed=0
|
||||||
|
failed=0
|
||||||
|
passed_runs=""
|
||||||
|
failed_runs=""
|
||||||
|
|
||||||
|
run_task() {
|
||||||
|
core="$1"
|
||||||
|
task="$2"
|
||||||
|
label="$core [$task]"
|
||||||
|
log_file=""
|
||||||
|
total=$((total + 1))
|
||||||
|
|
||||||
|
printf '\n[%d] Running formal %s for %s\n' "$total" "$task" "$core"
|
||||||
|
|
||||||
|
log_file=$(mktemp /tmp/check_formal.XXXXXX) || exit 2
|
||||||
|
|
||||||
|
if \
|
||||||
|
FUSESOC_CORE="$core" \
|
||||||
|
FUSESOC_TASK="$task" \
|
||||||
|
script -qefc 'fusesoc run --target formal "$FUSESOC_CORE" --taskname "$FUSESOC_TASK"' "$log_file" \
|
||||||
|
>/dev/null 2>&1
|
||||||
|
then
|
||||||
|
passed=$((passed + 1))
|
||||||
|
passed_runs="$passed_runs
|
||||||
|
$label"
|
||||||
|
printf 'Result: PASS (%s)\n' "$label"
|
||||||
|
rm -f "$log_file"
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
failed=$((failed + 1))
|
||||||
|
failed_runs="$failed_runs
|
||||||
|
$label"
|
||||||
|
printf 'Result: FAIL (%s)\n' "$label"
|
||||||
|
printf 'Captured log for %s:\n' "$label"
|
||||||
|
cat "$log_file" | grep summary
|
||||||
|
rm -f "$log_file"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
for core in $CORES; do
|
||||||
|
for task in $TASKS; do
|
||||||
|
run_task "$core" "$task"
|
||||||
|
done
|
||||||
|
done
|
||||||
|
|
||||||
|
printf '\nFormal run summary\n'
|
||||||
|
printf ' Total: %d\n' "$total"
|
||||||
|
printf ' Passed: %d\n' "$passed"
|
||||||
|
printf ' Failed: %d\n' "$failed"
|
||||||
|
|
||||||
|
if [ -n "$passed_runs" ]; then
|
||||||
|
printf '\nPassed runs:\n'
|
||||||
|
printf '%s\n' "$passed_runs" | while IFS= read -r run; do
|
||||||
|
if [ -n "$run" ]; then
|
||||||
|
printf ' - %s\n' "$run"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$failed_runs" ]; then
|
||||||
|
printf '\nFailed runs:\n'
|
||||||
|
printf '%s\n' "$failed_runs" | while IFS= read -r run; do
|
||||||
|
if [ -n "$run" ]; then
|
||||||
|
printf ' - %s\n' "$run"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$failed" -ne 0 ]; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
@@ -68,6 +68,31 @@ module formal_wb_master_checker (
|
|||||||
// R4: Once CYC is low, STB must also be low
|
// R4: Once CYC is low, STB must also be low
|
||||||
if(!i_wb_cyc)
|
if(!i_wb_cyc)
|
||||||
assert(!i_wb_stb);
|
assert(!i_wb_stb);
|
||||||
|
|
||||||
|
// C0: We eventually initiate a request
|
||||||
|
cover(f_past_valid && !i_rst && !i_wb_rst && i_wb_cyc && i_wb_stb);
|
||||||
|
|
||||||
|
// C1: We eventually get an ACK during an active request
|
||||||
|
cover(f_past_valid && !i_rst && !i_wb_rst && i_wb_cyc && i_wb_stb && o_wb_ack);
|
||||||
|
|
||||||
|
// C2: A delayed ACK occurs for a request issued in a previous cycle.
|
||||||
|
// This does not require the request to drop in the ACK cycle.
|
||||||
|
cover(f_past_valid && !i_rst && !i_wb_rst &&
|
||||||
|
$past(i_wb_cyc && i_wb_stb) && o_wb_ack);
|
||||||
|
|
||||||
|
// C4: A “wait state” happens: request asserted, no ACK for at least 1 cycle
|
||||||
|
cover(f_past_valid && !i_rst && !i_wb_rst &&
|
||||||
|
$past(i_wb_cyc && i_wb_stb && !o_wb_ack) &&
|
||||||
|
(i_wb_cyc && i_wb_stb && !o_wb_ack));
|
||||||
|
|
||||||
|
// C5: Read and write both occur (even if only once each)
|
||||||
|
cover(f_past_valid && !i_rst && !i_wb_rst && i_wb_cyc && i_wb_stb && !i_wb_we);
|
||||||
|
cover(f_past_valid && !i_rst && !i_wb_rst && i_wb_cyc && i_wb_stb && i_wb_we);
|
||||||
|
|
||||||
|
// C6: A transfer completes and the master drops CYC sometime after
|
||||||
|
cover(f_past_valid && !i_rst && !i_wb_rst &&
|
||||||
|
$past(i_wb_cyc && i_wb_stb && o_wb_ack) && !i_wb_cyc);
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
wire unused = &{1'b0, o_wb_rdt};
|
wire unused = &{1'b0, o_wb_rdt};
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
`timescale 1ns/1ps
|
`timescale 1ns/1ps
|
||||||
|
|
||||||
module formal_wb_slave_checker (
|
module formal_wb_slave_checker #(
|
||||||
|
parameter combinatorial_ack = 0
|
||||||
|
) (
|
||||||
input wire i_clk,
|
input wire i_clk,
|
||||||
input wire i_rst,
|
input wire i_rst,
|
||||||
input wire i_wb_rst,
|
input wire i_wb_rst,
|
||||||
@@ -62,6 +64,35 @@ module formal_wb_slave_checker (
|
|||||||
!i_wb_stb
|
!i_wb_stb
|
||||||
)
|
)
|
||||||
assert(!o_wb_ack);
|
assert(!o_wb_ack);
|
||||||
|
|
||||||
|
// C0: A request occurs at all
|
||||||
|
cover(f_past_valid && !i_rst && !i_wb_rst && i_wb_cyc && i_wb_stb);
|
||||||
|
|
||||||
|
// C1: A request with write and with read occur
|
||||||
|
cover(f_past_valid && !i_rst && !i_wb_rst && i_wb_cyc && i_wb_stb && i_wb_we);
|
||||||
|
cover(f_past_valid && !i_rst && !i_wb_rst && i_wb_cyc && i_wb_stb && !i_wb_we);
|
||||||
|
|
||||||
|
// C2: ACK happens during a request (basic progress)
|
||||||
|
cover(f_past_valid && !i_rst && !i_wb_rst && i_wb_cyc && i_wb_stb && o_wb_ack);
|
||||||
|
|
||||||
|
// C3: Exercise the expected ACK timing style for this slave.
|
||||||
|
if (combinatorial_ack) begin
|
||||||
|
cover(f_past_valid && !i_rst && !i_wb_rst &&
|
||||||
|
(i_wb_cyc && i_wb_stb) && o_wb_ack);
|
||||||
|
end else begin
|
||||||
|
cover(f_past_valid && !i_rst && !i_wb_rst &&
|
||||||
|
$past(i_wb_cyc && i_wb_stb) && o_wb_ack);
|
||||||
|
|
||||||
|
// C4: Wait-state behavior for registered/non-zero-wait slaves.
|
||||||
|
cover(f_past_valid && !i_rst && !i_wb_rst &&
|
||||||
|
$past(i_wb_cyc && i_wb_stb && !o_wb_ack) &&
|
||||||
|
(i_wb_cyc && i_wb_stb && !o_wb_ack));
|
||||||
|
end
|
||||||
|
|
||||||
|
// C5: Master ends a cycle (CYC drops) after at least one request
|
||||||
|
cover(f_past_valid && !i_rst && !i_wb_rst &&
|
||||||
|
$past(i_wb_cyc && i_wb_stb) && !i_wb_cyc);
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
wire unused = &{1'b0, o_wb_rdt};
|
wire unused = &{1'b0, o_wb_rdt};
|
||||||
|
|||||||
@@ -1,9 +1,19 @@
|
|||||||
|
[tasks]
|
||||||
|
prove
|
||||||
|
cover
|
||||||
|
bmc
|
||||||
|
|
||||||
[options]
|
[options]
|
||||||
mode prove
|
bmc: mode bmc
|
||||||
depth 8
|
bmc: depth 16
|
||||||
|
cover: mode cover
|
||||||
|
cover: depth 16
|
||||||
|
prove: mode prove
|
||||||
|
|
||||||
[engines]
|
[engines]
|
||||||
abc pdr
|
bmc: smtbmc yices
|
||||||
|
cover: smtbmc yices
|
||||||
|
prove: abc pdr
|
||||||
|
|
||||||
[script]
|
[script]
|
||||||
{{"-formal"|gen_reads}}
|
{{"-formal"|gen_reads}}
|
||||||
|
|||||||
@@ -1,13 +1,23 @@
|
|||||||
|
[tasks]
|
||||||
|
prove
|
||||||
|
cover
|
||||||
|
bmc
|
||||||
|
|
||||||
[options]
|
[options]
|
||||||
mode prove
|
bmc: mode bmc
|
||||||
depth 8
|
bmc: depth 50
|
||||||
|
cover: mode cover
|
||||||
|
cover: depth 50
|
||||||
|
prove: mode prove
|
||||||
|
|
||||||
[engines]
|
[engines]
|
||||||
smtbmc z3 parallel.enable=true parallel.threads.max=8
|
bmc: smtbmc yices
|
||||||
|
cover: smtbmc yices
|
||||||
|
prove: abc pdr
|
||||||
|
|
||||||
[script]
|
[script]
|
||||||
{{"-formal"|gen_reads}}
|
{{"-formal"|gen_reads}}
|
||||||
prep -top {{top_level}}
|
prep -top {{top_level}}
|
||||||
|
|
||||||
[files]
|
[files]
|
||||||
{{files}}
|
{{files}}
|
||||||
53
cores/wb/wb_gpio_banks/formal/formal_wb_gpio_banks.v
Normal file
53
cores/wb/wb_gpio_banks/formal/formal_wb_gpio_banks.v
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
`timescale 1ns/1ps
|
||||||
|
|
||||||
|
module formal_wb_gpio_banks #(
|
||||||
|
parameter integer NUM_BANKS = 2,
|
||||||
|
parameter [31:0] BASE_ADDR = 32'h00000000
|
||||||
|
);
|
||||||
|
(* gclk *) reg i_wb_clk;
|
||||||
|
(* anyseq *) reg i_rst;
|
||||||
|
(* anyseq *) reg i_wb_rst;
|
||||||
|
(* anyseq *) reg [31:0] i_wb_adr;
|
||||||
|
(* anyseq *) reg [31:0] i_wb_dat;
|
||||||
|
(* anyseq *) reg [3:0] i_wb_sel;
|
||||||
|
(* anyseq *) reg i_wb_we;
|
||||||
|
(* anyseq *) reg i_wb_stb;
|
||||||
|
(* anyseq *) reg [NUM_BANKS*32-1:0] i_gpio;
|
||||||
|
wire [31:0] o_wb_rdt;
|
||||||
|
wire o_wb_ack;
|
||||||
|
wire [NUM_BANKS*32-1:0] o_gpio;
|
||||||
|
wire i_wb_cyc;
|
||||||
|
|
||||||
|
assign i_wb_cyc = i_wb_stb || o_wb_ack;
|
||||||
|
|
||||||
|
wb_gpio_banks #(
|
||||||
|
.NUM_BANKS(NUM_BANKS),
|
||||||
|
.BASE_ADDR(BASE_ADDR)
|
||||||
|
) dut (
|
||||||
|
.i_wb_clk(i_wb_clk),
|
||||||
|
.i_wb_rst(i_wb_rst),
|
||||||
|
.i_wb_adr(i_wb_adr),
|
||||||
|
.i_wb_dat(i_wb_dat),
|
||||||
|
.i_wb_sel(i_wb_sel),
|
||||||
|
.i_wb_we(i_wb_we),
|
||||||
|
.i_wb_stb(i_wb_stb),
|
||||||
|
.i_gpio(i_gpio),
|
||||||
|
.o_wb_rdt(o_wb_rdt),
|
||||||
|
.o_wb_ack(o_wb_ack),
|
||||||
|
.o_gpio(o_gpio)
|
||||||
|
);
|
||||||
|
|
||||||
|
formal_wb_slave_checker wb_checker (
|
||||||
|
.i_clk(i_wb_clk),
|
||||||
|
.i_rst(i_rst),
|
||||||
|
.i_wb_rst(i_wb_rst),
|
||||||
|
.i_wb_adr(i_wb_adr),
|
||||||
|
.i_wb_dat(i_wb_dat),
|
||||||
|
.i_wb_sel(i_wb_sel),
|
||||||
|
.i_wb_we(i_wb_we),
|
||||||
|
.i_wb_stb(i_wb_stb),
|
||||||
|
.i_wb_cyc(i_wb_cyc),
|
||||||
|
.o_wb_rdt(o_wb_rdt),
|
||||||
|
.o_wb_ack(o_wb_ack)
|
||||||
|
);
|
||||||
|
endmodule
|
||||||
23
cores/wb/wb_gpio_banks/formal/wb_gpio_banks.sby
Normal file
23
cores/wb/wb_gpio_banks/formal/wb_gpio_banks.sby
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
[tasks]
|
||||||
|
prove
|
||||||
|
cover
|
||||||
|
bmc
|
||||||
|
|
||||||
|
[options]
|
||||||
|
bmc: mode bmc
|
||||||
|
bmc: depth 50
|
||||||
|
cover: mode cover
|
||||||
|
cover: depth 50
|
||||||
|
prove: mode prove
|
||||||
|
|
||||||
|
[engines]
|
||||||
|
bmc: smtbmc yices
|
||||||
|
cover: smtbmc yices
|
||||||
|
prove: abc pdr
|
||||||
|
|
||||||
|
[script]
|
||||||
|
{{"-formal"|gen_reads}}
|
||||||
|
prep -top {{top_level}}
|
||||||
|
|
||||||
|
[files]
|
||||||
|
{{files}}
|
||||||
@@ -10,6 +10,16 @@ filesets:
|
|||||||
files:
|
files:
|
||||||
- rtl/wb_gpio_banks.v
|
- rtl/wb_gpio_banks.v
|
||||||
file_type: verilogSource
|
file_type: verilogSource
|
||||||
|
formal_rtl:
|
||||||
|
depend:
|
||||||
|
- joppeb:wb:formal_checker
|
||||||
|
files:
|
||||||
|
- formal/formal_wb_gpio_banks.v
|
||||||
|
file_type: verilogSource
|
||||||
|
formal_cfg:
|
||||||
|
files:
|
||||||
|
- formal/wb_gpio_banks.sby
|
||||||
|
file_type: sbyConfigTemplate
|
||||||
|
|
||||||
targets:
|
targets:
|
||||||
default:
|
default:
|
||||||
@@ -19,6 +29,16 @@ targets:
|
|||||||
parameters:
|
parameters:
|
||||||
- NUM_BANKS
|
- NUM_BANKS
|
||||||
- BASE_ADDR
|
- BASE_ADDR
|
||||||
|
formal:
|
||||||
|
default_tool: symbiyosys
|
||||||
|
filesets:
|
||||||
|
- rtl
|
||||||
|
- formal_rtl
|
||||||
|
- formal_cfg
|
||||||
|
toplevel: formal_wb_gpio_banks
|
||||||
|
parameters:
|
||||||
|
- NUM_BANKS
|
||||||
|
- BASE_ADDR
|
||||||
|
|
||||||
parameters:
|
parameters:
|
||||||
NUM_BANKS:
|
NUM_BANKS:
|
||||||
|
|||||||
@@ -1,9 +1,19 @@
|
|||||||
|
[tasks]
|
||||||
|
prove
|
||||||
|
cover
|
||||||
|
bmc
|
||||||
|
|
||||||
[options]
|
[options]
|
||||||
mode prove
|
bmc: mode bmc
|
||||||
depth 8
|
bmc: depth 50
|
||||||
|
cover: mode cover
|
||||||
|
cover: depth 50
|
||||||
|
prove: mode prove
|
||||||
|
|
||||||
[engines]
|
[engines]
|
||||||
smtbmc z3 parallel.enable=true parallel.threads.max=8
|
bmc: smtbmc yices
|
||||||
|
cover: smtbmc yices
|
||||||
|
prove: abc pdr
|
||||||
|
|
||||||
[script]
|
[script]
|
||||||
read -formal clog2.vh
|
read -formal clog2.vh
|
||||||
@@ -12,4 +22,4 @@ prep -top {{top_level}}
|
|||||||
|
|
||||||
[files]
|
[files]
|
||||||
src/joppeb_util_clog2_1.0/clog2.vh
|
src/joppeb_util_clog2_1.0/clog2.vh
|
||||||
{{files}}
|
{{files}}
|
||||||
66
cores/wb/wb_timer/formal/formal_wb_timer.v
Normal file
66
cores/wb/wb_timer/formal/formal_wb_timer.v
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
`timescale 1ns/1ps
|
||||||
|
|
||||||
|
module formal_wb_timer #(
|
||||||
|
parameter WIDTH = 8,
|
||||||
|
parameter DIVIDER = 0
|
||||||
|
);
|
||||||
|
(* gclk *) reg i_clk;
|
||||||
|
(* anyseq *) reg i_rst;
|
||||||
|
(* anyseq *) reg [31:0] i_wb_adr;
|
||||||
|
(* anyseq *) reg [31:0] i_wb_dat;
|
||||||
|
(* anyseq *) reg [3:0] i_wb_sel;
|
||||||
|
(* anyseq *) reg i_wb_we;
|
||||||
|
(* anyseq *) reg i_wb_cyc;
|
||||||
|
(* anyseq *) reg i_wb_stb;
|
||||||
|
wire [31:0] o_wb_dat;
|
||||||
|
wire o_wb_ack;
|
||||||
|
wire o_irq;
|
||||||
|
wire i_wb_rst;
|
||||||
|
reg f_past_valid;
|
||||||
|
|
||||||
|
assign i_wb_rst = 1'b0;
|
||||||
|
|
||||||
|
wb_countdown_timer #(
|
||||||
|
.WIDTH(WIDTH),
|
||||||
|
.DIVIDER(DIVIDER)
|
||||||
|
) dut (
|
||||||
|
.i_clk(i_clk),
|
||||||
|
.i_rst(i_rst),
|
||||||
|
.o_irq(o_irq),
|
||||||
|
.i_wb_dat(i_wb_dat),
|
||||||
|
.o_wb_dat(o_wb_dat),
|
||||||
|
.i_wb_we(i_wb_we),
|
||||||
|
.i_wb_cyc(i_wb_cyc),
|
||||||
|
.i_wb_stb(i_wb_stb),
|
||||||
|
.o_wb_ack(o_wb_ack)
|
||||||
|
);
|
||||||
|
|
||||||
|
formal_wb_slave_checker #(
|
||||||
|
.combinatorial_ack(1)
|
||||||
|
) wb_checker (
|
||||||
|
.i_clk(i_clk),
|
||||||
|
.i_rst(i_rst),
|
||||||
|
.i_wb_rst(i_wb_rst),
|
||||||
|
.i_wb_adr(i_wb_adr),
|
||||||
|
.i_wb_dat(i_wb_dat),
|
||||||
|
.i_wb_sel(i_wb_sel),
|
||||||
|
.i_wb_we(i_wb_we),
|
||||||
|
.i_wb_stb(i_wb_stb),
|
||||||
|
.i_wb_cyc(i_wb_cyc),
|
||||||
|
.o_wb_rdt(o_wb_dat),
|
||||||
|
.o_wb_ack(o_wb_ack)
|
||||||
|
);
|
||||||
|
|
||||||
|
initial f_past_valid = 1'b0;
|
||||||
|
|
||||||
|
always @(posedge i_clk) begin
|
||||||
|
f_past_valid <= 1'b1;
|
||||||
|
|
||||||
|
// Keep the bus idle on the first cycle after reset so the zero-wait ACK
|
||||||
|
// does not collide with the generic slave checker's post-reset rule.
|
||||||
|
if (f_past_valid && $past(i_rst)) begin
|
||||||
|
assume(!i_wb_cyc);
|
||||||
|
assume(!i_wb_stb);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
23
cores/wb/wb_timer/formal/wb_timer.sby
Normal file
23
cores/wb/wb_timer/formal/wb_timer.sby
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
[tasks]
|
||||||
|
prove
|
||||||
|
cover
|
||||||
|
bmc
|
||||||
|
|
||||||
|
[options]
|
||||||
|
bmc: mode bmc
|
||||||
|
bmc: depth 50
|
||||||
|
cover: mode cover
|
||||||
|
cover: depth 50
|
||||||
|
prove: mode prove
|
||||||
|
|
||||||
|
[engines]
|
||||||
|
bmc: smtbmc yices
|
||||||
|
cover: smtbmc yices
|
||||||
|
prove: abc pdr
|
||||||
|
|
||||||
|
[script]
|
||||||
|
{{"-formal"|gen_reads}}
|
||||||
|
prep -top {{top_level}}
|
||||||
|
|
||||||
|
[files]
|
||||||
|
{{files}}
|
||||||
@@ -8,6 +8,16 @@ filesets:
|
|||||||
files:
|
files:
|
||||||
- rtl/wb_timer.v
|
- rtl/wb_timer.v
|
||||||
file_type: verilogSource
|
file_type: verilogSource
|
||||||
|
formal_rtl:
|
||||||
|
depend:
|
||||||
|
- joppeb:wb:formal_checker
|
||||||
|
files:
|
||||||
|
- formal/formal_wb_timer.v
|
||||||
|
file_type: verilogSource
|
||||||
|
formal_cfg:
|
||||||
|
files:
|
||||||
|
- formal/wb_timer.sby
|
||||||
|
file_type: sbyConfigTemplate
|
||||||
|
|
||||||
targets:
|
targets:
|
||||||
default:
|
default:
|
||||||
@@ -17,6 +27,16 @@ targets:
|
|||||||
parameters:
|
parameters:
|
||||||
- WIDTH
|
- WIDTH
|
||||||
- DIVIDER
|
- DIVIDER
|
||||||
|
formal:
|
||||||
|
default_tool: symbiyosys
|
||||||
|
filesets:
|
||||||
|
- rtl
|
||||||
|
- formal_rtl
|
||||||
|
- formal_cfg
|
||||||
|
toplevel: formal_wb_timer
|
||||||
|
parameters:
|
||||||
|
- WIDTH
|
||||||
|
- DIVIDER
|
||||||
|
|
||||||
parameters:
|
parameters:
|
||||||
WIDTH:
|
WIDTH:
|
||||||
|
|||||||
Reference in New Issue
Block a user