pg-verify 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/Gemfile +10 -0
- data/Gemfile.lock +98 -0
- data/README.md +29 -0
- data/Rakefile +62 -0
- data/bin/console +15 -0
- data/bin/pg-verify.rb +18 -0
- data/bin/setup +8 -0
- data/calc.ebnf +21 -0
- data/data/config/pg-verify.yml +66 -0
- data/data/nusmv.sample.smv +179 -0
- data/data/project-template/.gitignore.resource +4 -0
- data/data/project-template/.pg-verify.yml +0 -0
- data/data/project-template/README.md +18 -0
- data/data/project-template/addon/.keep +0 -0
- data/data/project-template/program-graph.rb.resource +103 -0
- data/devpg +5 -0
- data/doc/examples/railroad_crossing.rb +61 -0
- data/doc/examples/train-tree.rb +43 -0
- data/doc/examples/weidezaun.rb +99 -0
- data/doc/examples/weidezaun.txt +29 -0
- data/doc/expose/definition.png +0 -0
- data/doc/expose/diagram.png +0 -0
- data/doc/expose/expose.md +359 -0
- data/doc/expose/validity.png +0 -0
- data/exe/pg-verify +4 -0
- data/integration_tests/ruby_dsl/001_states.rb +10 -0
- data/integration_tests/ruby_dsl/002_transitions.rb +10 -0
- data/integration_tests/ruby_dsl/003_actions.rb +14 -0
- data/integration_tests/ruby_dsl/004_guards.rb +18 -0
- data/integration_tests/ruby_dsl/005_variables.rb +16 -0
- data/integration_tests/ruby_dsl/006_state_variables.rb +26 -0
- data/integration_tests/ruby_dsl/007_variable_initialization.rb +28 -0
- data/integration_tests/ruby_dsl/008_state_initialization.rb +19 -0
- data/integration_tests/ruby_dsl/009_shared_variables.rb +26 -0
- data/integration_tests/ruby_dsl/010_complex_guards.rb +18 -0
- data/integration_tests/ruby_dsl/011_complex_actions.rb +16 -0
- data/integration_tests/ruby_dsl/012_error_components.rb +9 -0
- data/integration_tests/ruby_dsl/013_hazards.rb +25 -0
- data/integration_tests/ruby_dsl/014_tau_transitions.rb +26 -0
- data/integration_tests/ruby_dsl/015_basic_dcca.rb +19 -0
- data/integration_tests/ruby_dsl/016_pressure_tank.rb +146 -0
- data/lib/pg-verify/cli/cli.rb +235 -0
- data/lib/pg-verify/core/cmd_runner.rb +151 -0
- data/lib/pg-verify/core/core.rb +38 -0
- data/lib/pg-verify/core/extensions/array_extensions.rb +11 -0
- data/lib/pg-verify/core/extensions/enumerable_extensions.rb +19 -0
- data/lib/pg-verify/core/extensions/nil_extensions.rb +7 -0
- data/lib/pg-verify/core/extensions/string_extensions.rb +84 -0
- data/lib/pg-verify/core/shell/colorizer.rb +136 -0
- data/lib/pg-verify/core/shell/shell.rb +0 -0
- data/lib/pg-verify/core/util.rb +146 -0
- data/lib/pg-verify/doctor/doctor.rb +180 -0
- data/lib/pg-verify/ebnf_parser/ast.rb +31 -0
- data/lib/pg-verify/ebnf_parser/ebnf_parser.rb +26 -0
- data/lib/pg-verify/ebnf_parser/expression_parser.rb +177 -0
- data/lib/pg-verify/ebnf_parser/expression_parser2.rb +422 -0
- data/lib/pg-verify/ebnf_parser/expressions.ebnf +33 -0
- data/lib/pg-verify/ebnf_parser/expressions.peg +52 -0
- data/lib/pg-verify/ebnf_parser/parser_result.rb +26 -0
- data/lib/pg-verify/interpret/component_context.rb +125 -0
- data/lib/pg-verify/interpret/graph_context.rb +85 -0
- data/lib/pg-verify/interpret/interpret.rb +142 -0
- data/lib/pg-verify/interpret/pg_script.rb +72 -0
- data/lib/pg-verify/interpret/spec/ltl_builder.rb +90 -0
- data/lib/pg-verify/interpret/spec/spec_context.rb +32 -0
- data/lib/pg-verify/interpret/spec/spec_set_context.rb +67 -0
- data/lib/pg-verify/interpret/transition_context.rb +55 -0
- data/lib/pg-verify/model/allocation_set.rb +28 -0
- data/lib/pg-verify/model/assignment.rb +34 -0
- data/lib/pg-verify/model/component.rb +40 -0
- data/lib/pg-verify/model/dcca/hazard.rb +16 -0
- data/lib/pg-verify/model/dcca.rb +67 -0
- data/lib/pg-verify/model/expression.rb +106 -0
- data/lib/pg-verify/model/graph.rb +58 -0
- data/lib/pg-verify/model/model.rb +10 -0
- data/lib/pg-verify/model/parsed_expression.rb +77 -0
- data/lib/pg-verify/model/simulation/trace.rb +43 -0
- data/lib/pg-verify/model/simulation/variable_state.rb +23 -0
- data/lib/pg-verify/model/source_location.rb +45 -0
- data/lib/pg-verify/model/specs/spec.rb +44 -0
- data/lib/pg-verify/model/specs/spec_result.rb +25 -0
- data/lib/pg-verify/model/specs/spec_set.rb +43 -0
- data/lib/pg-verify/model/specs/specification.rb +50 -0
- data/lib/pg-verify/model/transition.rb +41 -0
- data/lib/pg-verify/model/validation/assignment_to_state_variable_validation.rb +26 -0
- data/lib/pg-verify/model/validation/empty_state_set_validation.rb +18 -0
- data/lib/pg-verify/model/validation/errors.rb +119 -0
- data/lib/pg-verify/model/validation/foreign_assignment_validation.rb +30 -0
- data/lib/pg-verify/model/validation/unknown_token_validation.rb +35 -0
- data/lib/pg-verify/model/validation/validation.rb +23 -0
- data/lib/pg-verify/model/variable.rb +47 -0
- data/lib/pg-verify/model/variable_set.rb +84 -0
- data/lib/pg-verify/nusmv/nusmv.rb +23 -0
- data/lib/pg-verify/nusmv/runner.rb +124 -0
- data/lib/pg-verify/puml/puml.rb +23 -0
- data/lib/pg-verify/shell/loading/line_animation.rb +36 -0
- data/lib/pg-verify/shell/loading/loading_animation.rb +80 -0
- data/lib/pg-verify/shell/loading/loading_prompt.rb +43 -0
- data/lib/pg-verify/shell/loading/no_animation.rb +20 -0
- data/lib/pg-verify/shell/shell.rb +30 -0
- data/lib/pg-verify/simulation/simulation.rb +7 -0
- data/lib/pg-verify/simulation/simulator.rb +90 -0
- data/lib/pg-verify/simulation/state.rb +53 -0
- data/lib/pg-verify/transform/hash_transformation.rb +104 -0
- data/lib/pg-verify/transform/nusmv_transformation.rb +261 -0
- data/lib/pg-verify/transform/puml_transformation.rb +89 -0
- data/lib/pg-verify/transform/transform.rb +8 -0
- data/lib/pg-verify/version.rb +5 -0
- data/lib/pg-verify.rb +47 -0
- data/pg-verify.gemspec +38 -0
- data/sig/pg-verify.rbs +4 -0
- metadata +226 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: '0582b670fd565351fe5f6f01f34e5dd7358f4fd6f2385ced16d7a487c0b65a8d'
|
4
|
+
data.tar.gz: ea5556b7831154f0330e96e145be74fba25a31d5a775dc5e6abc5d32eaba9b03
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: fb81fb19377bda7a3c109a5dfb7ee4174c5d529a3133223b784ff814bc68636487664ed07ce8cc6f39eed1cdf99ebd3e20ac027ab5a19da9416f32f6977a5105
|
7
|
+
data.tar.gz: 5453f990cda9252b0be7b9e6c0a71ce8f1d8fc77f064ef5f3f6eb29c03dbb1a5a44f370e54b8137398c02c0a3643a9135558ea5c20066684545618ab60f5de94
|
data/.rspec
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
pg-verify (0.1.0)
|
5
|
+
config (~> 4.2.1)
|
6
|
+
ebnf (~> 2.3.4)
|
7
|
+
plantuml_builder (~> 0.3.0)
|
8
|
+
rainbow (~> 3.0.0)
|
9
|
+
thor (~> 1.2.1)
|
10
|
+
|
11
|
+
GEM
|
12
|
+
remote: https://rubygems.org/
|
13
|
+
specs:
|
14
|
+
concurrent-ruby (1.2.2)
|
15
|
+
config (4.2.1)
|
16
|
+
deep_merge (~> 1.2, >= 1.2.1)
|
17
|
+
dry-validation (~> 1.0, >= 1.0.0)
|
18
|
+
deep_merge (1.2.2)
|
19
|
+
diff-lcs (1.5.0)
|
20
|
+
docopt (0.5.0)
|
21
|
+
dry-configurable (0.13.0)
|
22
|
+
concurrent-ruby (~> 1.0)
|
23
|
+
dry-core (~> 0.6)
|
24
|
+
dry-container (0.9.0)
|
25
|
+
concurrent-ruby (~> 1.0)
|
26
|
+
dry-configurable (~> 0.13, >= 0.13.0)
|
27
|
+
dry-core (0.7.1)
|
28
|
+
concurrent-ruby (~> 1.0)
|
29
|
+
dry-inflector (0.2.1)
|
30
|
+
dry-initializer (3.0.4)
|
31
|
+
dry-logic (1.2.0)
|
32
|
+
concurrent-ruby (~> 1.0)
|
33
|
+
dry-core (~> 0.5, >= 0.5)
|
34
|
+
dry-schema (1.8.0)
|
35
|
+
concurrent-ruby (~> 1.0)
|
36
|
+
dry-configurable (~> 0.13, >= 0.13.0)
|
37
|
+
dry-core (~> 0.5, >= 0.5)
|
38
|
+
dry-initializer (~> 3.0)
|
39
|
+
dry-logic (~> 1.0)
|
40
|
+
dry-types (~> 1.5)
|
41
|
+
dry-types (1.5.1)
|
42
|
+
concurrent-ruby (~> 1.0)
|
43
|
+
dry-container (~> 0.3)
|
44
|
+
dry-core (~> 0.5, >= 0.5)
|
45
|
+
dry-inflector (~> 0.1, >= 0.1.2)
|
46
|
+
dry-logic (~> 1.0, >= 1.0.2)
|
47
|
+
dry-validation (1.7.0)
|
48
|
+
concurrent-ruby (~> 1.0)
|
49
|
+
dry-container (~> 0.7, >= 0.7.1)
|
50
|
+
dry-core (~> 0.5, >= 0.5)
|
51
|
+
dry-initializer (~> 3.0)
|
52
|
+
dry-schema (~> 1.8, >= 1.8.0)
|
53
|
+
ebnf (2.3.4)
|
54
|
+
htmlentities (~> 4.3)
|
55
|
+
rdf (~> 3.2)
|
56
|
+
scanf (~> 1.0)
|
57
|
+
sxp (~> 1.2)
|
58
|
+
unicode-types (~> 1.8)
|
59
|
+
htmlentities (4.3.4)
|
60
|
+
link_header (0.0.8)
|
61
|
+
matrix (0.4.2)
|
62
|
+
plantuml_builder (0.3.0)
|
63
|
+
docopt (~> 0.5.0)
|
64
|
+
rainbow (3.0.0)
|
65
|
+
rake (13.0.6)
|
66
|
+
rdf (3.2.11)
|
67
|
+
link_header (~> 0.0, >= 0.0.8)
|
68
|
+
rspec (3.12.0)
|
69
|
+
rspec-core (~> 3.12.0)
|
70
|
+
rspec-expectations (~> 3.12.0)
|
71
|
+
rspec-mocks (~> 3.12.0)
|
72
|
+
rspec-core (3.12.0)
|
73
|
+
rspec-support (~> 3.12.0)
|
74
|
+
rspec-expectations (3.12.1)
|
75
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
76
|
+
rspec-support (~> 3.12.0)
|
77
|
+
rspec-mocks (3.12.1)
|
78
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
79
|
+
rspec-support (~> 3.12.0)
|
80
|
+
rspec-support (3.12.0)
|
81
|
+
scanf (1.0.0)
|
82
|
+
sxp (1.2.4)
|
83
|
+
matrix (~> 0.4)
|
84
|
+
rdf (~> 3.2)
|
85
|
+
thor (1.2.1)
|
86
|
+
unicode-types (1.8.0)
|
87
|
+
|
88
|
+
PLATFORMS
|
89
|
+
x86_64-darwin-19
|
90
|
+
x86_64-linux
|
91
|
+
|
92
|
+
DEPENDENCIES
|
93
|
+
pg-verify!
|
94
|
+
rake (~> 13.0)
|
95
|
+
rspec (~> 3.0)
|
96
|
+
|
97
|
+
BUNDLED WITH
|
98
|
+
2.3.26
|
data/README.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# PgVerify
|
2
|
+
|
3
|
+
Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/pg-verify`. To experiment with that code, run `bin/console` for an interactive prompt.
|
4
|
+
|
5
|
+
TODO: Delete this and the text above, and describe your gem
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Install the gem and add to the application's Gemfile by executing:
|
10
|
+
|
11
|
+
$ bundle add pg-verify
|
12
|
+
|
13
|
+
If bundler is not being used to manage dependencies, install the gem by executing:
|
14
|
+
|
15
|
+
$ gem install pg-verify
|
16
|
+
|
17
|
+
## Usage
|
18
|
+
|
19
|
+
TODO: Write usage instructions here
|
20
|
+
|
21
|
+
## Development
|
22
|
+
|
23
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
24
|
+
|
25
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
26
|
+
|
27
|
+
## Contributing
|
28
|
+
|
29
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/pg-verify.
|
data/Rakefile
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "bundler/gem_tasks"
|
4
|
+
require "rspec/core/rake_task"
|
5
|
+
|
6
|
+
RSpec::Core::RakeTask.new(:spec)
|
7
|
+
|
8
|
+
task default: :spec
|
9
|
+
|
10
|
+
task :itest do
|
11
|
+
versions = [ "3.0", "2.6" ]
|
12
|
+
versions.each { |v| test_ruby_version(v) }
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
def test_ruby_version(version)
|
17
|
+
|
18
|
+
message = "Running tests on ruby v#{version}"
|
19
|
+
puts "#" * message.length
|
20
|
+
puts message
|
21
|
+
puts "#" * message.length
|
22
|
+
|
23
|
+
FileUtils.rm_rf(".pg-work")
|
24
|
+
FileUtils.mkdir(".pg-work")
|
25
|
+
|
26
|
+
# Generate docker file
|
27
|
+
dockerfile_path = File.join(".pg-work", "Dockerfile")
|
28
|
+
image_name = "pg-verify-test"
|
29
|
+
dockerfile = [ "FROM ruby:#{version}" ]
|
30
|
+
File.write(dockerfile_path, dockerfile.join("\n"))
|
31
|
+
sh "docker build --file #{dockerfile_path} --tag #{image_name} ."
|
32
|
+
|
33
|
+
test_cmd = []
|
34
|
+
test_cmd << "rm -f Gemfile.lock"
|
35
|
+
test_cmd << "bundle config set without packaging documentation"
|
36
|
+
test_cmd << "gem update --system --silent --no-document"
|
37
|
+
test_cmd << "bundle lock"
|
38
|
+
test_cmd << "bundle install --path /tmp/gems"
|
39
|
+
test_cmd << "ruby --version"
|
40
|
+
test_cmd << "bundle exec rspec"
|
41
|
+
test_cmd << "bundle exec rake build"
|
42
|
+
test_cmd << "gem install pkg/*"
|
43
|
+
test_cmd << "pg-verify --help"
|
44
|
+
test_cmd << "pg-verify doctor"
|
45
|
+
test_cmd = test_cmd.join(" && ")
|
46
|
+
|
47
|
+
docker_run = [ "docker run" ]
|
48
|
+
docker_run << "--rm"
|
49
|
+
docker_run << "--name pg-verify-container"
|
50
|
+
docker_run << "--mount type=bind,source='#{Dir.pwd}',target=/app"
|
51
|
+
docker_run << "--workdir /app"
|
52
|
+
docker_run << image_name
|
53
|
+
docker_run << "bash -c \"#{test_cmd}\""
|
54
|
+
docker_run = docker_run.join(" ")
|
55
|
+
|
56
|
+
sh docker_run
|
57
|
+
|
58
|
+
gem_file = Dir[File.join("pkg", "*.gem")].first
|
59
|
+
FileUtils.mkdir_p("out")
|
60
|
+
out_path = File.join("out", File.basename(gem_file).gsub(".gem", "-r#{version}.gem"))
|
61
|
+
mv gem_file, out_path
|
62
|
+
end
|
data/bin/console
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "bundler/setup"
|
5
|
+
require "pg-verify"
|
6
|
+
|
7
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
8
|
+
# with your gem easier. You can also use a different console, if you like.
|
9
|
+
|
10
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
11
|
+
# require "pry"
|
12
|
+
# Pry.start
|
13
|
+
|
14
|
+
require "irb"
|
15
|
+
IRB.start(__FILE__)
|
data/bin/pg-verify.rb
ADDED
data/bin/setup
ADDED
data/calc.ebnf
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
[1] Assignment ::= VARIABLE ':=' IntExpr
|
2
|
+
[2] Expression ::= BoolExpr
|
3
|
+
|
4
|
+
[3] BoolExpr ::= Equivalence
|
5
|
+
[4] Equivalence ::= Implication (('<->' | '<!>') Implication)*
|
6
|
+
[5] Implication ::= Disjunction ('=>' Disjunction)*
|
7
|
+
[6] Disjunction ::= Konjunction ('||' Konjunction)*
|
8
|
+
[7] Konjunction ::= Negation ('&&' Negation)*
|
9
|
+
[8] Negation ::= '!' Comparison | Comparison
|
10
|
+
|
11
|
+
[9] Comparison ::= Sum (CMPOP Sum)*
|
12
|
+
|
13
|
+
[10] IntExpr ::= Sum
|
14
|
+
[11] Sum ::= Product (('+' | '-') Product)*
|
15
|
+
[12] Product ::= Value (('*' | '/') Value)*
|
16
|
+
[13] Value ::= NUMBER | BOOL | VARIABLE | '(' Expression ')'
|
17
|
+
|
18
|
+
[14] NUMBER ::= [0-9]+
|
19
|
+
[15] BOOL ::= 'true' | 'false'
|
20
|
+
[16] VARIABLE ::= [a-zA-Z_][a-zA-Z0-9_]*
|
21
|
+
[17] CMPOP ::= '<=' | '>=' | '<' | '>' | '==' | '!='
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# The working directory for temporary files and caches
|
2
|
+
workdir: <%= File.expand_path('.pg-work', Dir.pwd) %>
|
3
|
+
|
4
|
+
# The default output directory for generated files like images
|
5
|
+
outdir: <%= File.expand_path('out', Dir.pwd) %>
|
6
|
+
|
7
|
+
# Configuration for the NuSMV addon
|
8
|
+
nusmv:
|
9
|
+
# Path the the NuSMV executable. Can be omitted if NuSMV is dropped into the addon/ dir
|
10
|
+
path: null
|
11
|
+
|
12
|
+
# Configuration for the PlantUML addon
|
13
|
+
puml:
|
14
|
+
active_state_color: "#FF0000/FFFF00"
|
15
|
+
path: null
|
16
|
+
|
17
|
+
# Configuration for the Ruby DSL
|
18
|
+
ruby_dsl:
|
19
|
+
# Default model definition script file when pg-verify is invoked without arguments
|
20
|
+
default_script_name: "program-graph.rb"
|
21
|
+
|
22
|
+
# Enable/Disable colored printing all together
|
23
|
+
use_colors: true
|
24
|
+
# Enable/Disable colored printing when the output of pg-verify
|
25
|
+
# is not piped into a TTY directly.
|
26
|
+
use_colors_in_pipe: false
|
27
|
+
# Print full stack traces on any error.
|
28
|
+
full_stack_trace: false
|
29
|
+
# Enable/Disable shell animations
|
30
|
+
use_animations: true
|
31
|
+
print_loading_times: true
|
32
|
+
allow_right_print: true
|
33
|
+
|
34
|
+
trace:
|
35
|
+
# Colorize certain values while printing traces
|
36
|
+
colors:
|
37
|
+
Closed: green
|
38
|
+
Open: red
|
39
|
+
|
40
|
+
# Colors theme for the TTY
|
41
|
+
theme:
|
42
|
+
state: ["deepskyblue", "bold"]
|
43
|
+
trans: [ "springgreen", "italic" ]
|
44
|
+
var: [ "limegreen", "italic" ]
|
45
|
+
cmp: ["deepskyblue", "bold", "italic"]
|
46
|
+
num: dodgerblue
|
47
|
+
literal: dodgerblue
|
48
|
+
string: orange
|
49
|
+
success: springgreen
|
50
|
+
warn: khaki
|
51
|
+
error: red
|
52
|
+
sidenote: "darkslategray"
|
53
|
+
file: [ "limegreen", "bold" ]
|
54
|
+
expression: ["deepskyblue", "italic"]
|
55
|
+
command: ["deepskyblue", "italic"]
|
56
|
+
|
57
|
+
prompt:
|
58
|
+
prompt_format: " %s"
|
59
|
+
debug: "D "
|
60
|
+
verbose: "V "
|
61
|
+
info: "➜ "
|
62
|
+
warn: "âš¡"
|
63
|
+
error: "✘ "
|
64
|
+
empty: "~ "
|
65
|
+
success: "✓ "
|
66
|
+
question: "» "
|
@@ -0,0 +1,179 @@
|
|
1
|
+
MODULE cache-device
|
2
|
+
|
3
|
+
VAR
|
4
|
+
state : {invalid,shared,owned};
|
5
|
+
|
6
|
+
|
7
|
+
DEFINE
|
8
|
+
readable := ((state = shared) | (state = owned)) & !waiting;
|
9
|
+
writable := (state = owned) & !waiting;
|
10
|
+
|
11
|
+
ASSIGN
|
12
|
+
init(state) := invalid;
|
13
|
+
next(state) :=
|
14
|
+
case
|
15
|
+
abort : state;
|
16
|
+
master :
|
17
|
+
case
|
18
|
+
CMD = read-shared : shared;
|
19
|
+
CMD = read-owned : owned;
|
20
|
+
CMD = write-invalid : invalid;
|
21
|
+
CMD = write-resp-invalid : invalid;
|
22
|
+
CMD = write-shared : shared;
|
23
|
+
CMD = write-resp-shared : shared;
|
24
|
+
TRUE : state;
|
25
|
+
esac;
|
26
|
+
!master & state = shared & (CMD = read-owned | CMD = invalidate) :
|
27
|
+
invalid;
|
28
|
+
state = shared : {shared,invalid};
|
29
|
+
TRUE : state;
|
30
|
+
esac;
|
31
|
+
|
32
|
+
DEFINE
|
33
|
+
reply-owned := !master & state = owned;
|
34
|
+
|
35
|
+
VAR
|
36
|
+
snoop : {invalid,owned,shared};
|
37
|
+
|
38
|
+
ASSIGN
|
39
|
+
init(snoop) := invalid;
|
40
|
+
next(snoop) :=
|
41
|
+
case
|
42
|
+
abort : snoop;
|
43
|
+
!master & state = owned & CMD = read-shared : shared;
|
44
|
+
!master & state = owned & CMD = read-shared : owned;
|
45
|
+
master & CMD = write-resp-invalid : invalid;
|
46
|
+
master & CMD = write-resp-shared : invalid;
|
47
|
+
TRUE : snoop;
|
48
|
+
esac;
|
49
|
+
|
50
|
+
MODULE bus-device
|
51
|
+
|
52
|
+
VAR
|
53
|
+
master : boolean;
|
54
|
+
cmd : {idle,read-shared,read-owned,write-invalid,write-shared,
|
55
|
+
write-resp-invalid,write-resp-shared,invalidate,response};
|
56
|
+
waiting : boolean;
|
57
|
+
reply-stall : boolean;
|
58
|
+
|
59
|
+
ASSIGN
|
60
|
+
init(waiting) := FALSE;
|
61
|
+
next(waiting) :=
|
62
|
+
case
|
63
|
+
abort : waiting;
|
64
|
+
master & CMD = read-shared : TRUE;
|
65
|
+
master & CMD = read-owned : TRUE;
|
66
|
+
!master & CMD = response : FALSE;
|
67
|
+
!master & CMD = write-resp-invalid : FALSE;
|
68
|
+
!master & CMD = write-resp-shared : FALSE;
|
69
|
+
TRUE : waiting;
|
70
|
+
esac;
|
71
|
+
|
72
|
+
DEFINE
|
73
|
+
reply-waiting := !master & waiting;
|
74
|
+
abort := REPLY-STALL
|
75
|
+
| ((CMD = read-shared | CMD = read-owned) & REPLY-WAITING);
|
76
|
+
|
77
|
+
MODULE processor(CMD,REPLY-OWNED,REPLY-WAITING,REPLY-STALL)
|
78
|
+
ISA bus-device
|
79
|
+
ISA cache-device
|
80
|
+
|
81
|
+
ASSIGN
|
82
|
+
cmd :=
|
83
|
+
case
|
84
|
+
master & state = invalid : {read-shared,read-owned};
|
85
|
+
master & state = shared : read-owned;
|
86
|
+
master & state = owned & snoop = owned : write-resp-invalid;
|
87
|
+
master & state = owned & snoop = shared : write-resp-shared;
|
88
|
+
master & state = owned & snoop = invalid : write-invalid;
|
89
|
+
TRUE : idle;
|
90
|
+
esac;
|
91
|
+
|
92
|
+
MODULE memory(CMD,REPLY-OWNED,REPLY-WAITING,REPLY-STALL)
|
93
|
+
VAR
|
94
|
+
master : boolean;
|
95
|
+
cmd : {idle,read-shared,read-owned,write-invalid,write-shared,
|
96
|
+
write-resp-invalid,write-resp-shared,invalidate,response};
|
97
|
+
busy : boolean;
|
98
|
+
reply-stall : boolean;
|
99
|
+
|
100
|
+
|
101
|
+
DEFINE
|
102
|
+
reply-owned := FALSE;
|
103
|
+
reply-waiting := FALSE;
|
104
|
+
abort := REPLY-STALL
|
105
|
+
| (CMD = read-shared | CMD = read-owned) & REPLY-WAITING
|
106
|
+
| (CMD = read-shared | CMD = read-owned) & REPLY-OWNED;
|
107
|
+
|
108
|
+
ASSIGN
|
109
|
+
init(busy) := FALSE;
|
110
|
+
next(busy) :=
|
111
|
+
case
|
112
|
+
abort : busy;
|
113
|
+
master & CMD = response : FALSE;
|
114
|
+
!master & (CMD = read-owned | CMD = read-shared) : TRUE;
|
115
|
+
TRUE : busy;
|
116
|
+
esac;
|
117
|
+
cmd :=
|
118
|
+
case
|
119
|
+
master & busy : {response,idle};
|
120
|
+
TRUE : idle;
|
121
|
+
esac;
|
122
|
+
reply-stall :=
|
123
|
+
case
|
124
|
+
busy & (CMD = read-shared | CMD = read-owned
|
125
|
+
| CMD = write-invalid | CMD = write-shared
|
126
|
+
| CMD = write-resp-invalid | CMD = write-resp-shared) : TRUE;
|
127
|
+
TRUE : {FALSE,TRUE};
|
128
|
+
esac;
|
129
|
+
|
130
|
+
MODULE main
|
131
|
+
VAR
|
132
|
+
CMD : {idle,read-shared,read-owned,write-invalid,write-shared,
|
133
|
+
write-resp-invalid,write-resp-shared,invalidate,response};
|
134
|
+
p0 : processor(CMD,REPLY-OWNED,REPLY-WAITING,REPLY-STALL);
|
135
|
+
p1 : processor(CMD,REPLY-OWNED,REPLY-WAITING,REPLY-STALL);
|
136
|
+
p2 : processor(CMD,REPLY-OWNED,REPLY-WAITING,REPLY-STALL);
|
137
|
+
m : memory(CMD,REPLY-OWNED,REPLY-WAITING,REPLY-STALL);
|
138
|
+
|
139
|
+
DEFINE
|
140
|
+
REPLY-OWNED := p0.reply-owned | p1.reply-owned | p2.reply-owned;
|
141
|
+
REPLY-WAITING := p0.reply-waiting | p1.reply-waiting | p2.reply-waiting;
|
142
|
+
REPLY-STALL := p0.reply-stall | p1.reply-stall | p2.reply-stall |
|
143
|
+
m.reply-stall;
|
144
|
+
|
145
|
+
ASSIGN
|
146
|
+
CMD :=
|
147
|
+
case
|
148
|
+
p1.cmd = idle & p2.cmd = idle & m.cmd = idle : p0.cmd;
|
149
|
+
p0.cmd = idle & p2.cmd = idle & m.cmd = idle : p1.cmd;
|
150
|
+
p0.cmd = idle & p1.cmd = idle & m.cmd = idle : p2.cmd;
|
151
|
+
p0.cmd = idle & p1.cmd = idle & p2.cmd = idle : m.cmd;
|
152
|
+
TRUE : {idle,read-shared,read-owned,write-invalid,write-shared,
|
153
|
+
write-resp-invalid,write-resp-shared,invalidate,response};
|
154
|
+
esac;
|
155
|
+
|
156
|
+
ASSIGN
|
157
|
+
p0.master := {FALSE,TRUE};
|
158
|
+
p1.master :=
|
159
|
+
case
|
160
|
+
p0.master : FALSE;
|
161
|
+
TRUE : {FALSE,TRUE};
|
162
|
+
esac;
|
163
|
+
p2.master :=
|
164
|
+
case
|
165
|
+
p0.master | p1.master : FALSE;
|
166
|
+
TRUE : {FALSE,TRUE};
|
167
|
+
esac;
|
168
|
+
m.master :=
|
169
|
+
case
|
170
|
+
p0.master | p1.master | p2.master : FALSE;
|
171
|
+
TRUE : {FALSE,TRUE};
|
172
|
+
esac;
|
173
|
+
|
174
|
+
SPEC
|
175
|
+
AG EF (p0.readable)
|
176
|
+
SPEC
|
177
|
+
AG EF (p0.writable)
|
178
|
+
SPEC
|
179
|
+
AG !(p0.writable & p1.writable)
|
File without changes
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# Welcome to your project 🎉
|
2
|
+
|
3
|
+
PG verify is a CLI application which allows you to develop program graph models
|
4
|
+
and verify characteristics of those models.
|
5
|
+
|
6
|
+
To get started you can run `pg-verify doctor` to verify your installation and guide
|
7
|
+
you through the steps needed to install external addons like the NuSMV model checker.
|
8
|
+
|
9
|
+
You can always run `pg-verify help` to get a list of available commands.
|
10
|
+
For example try running `pg-verify show png` to render a PNG image of your program graph
|
11
|
+
and save that to your working directory.
|
12
|
+
|
13
|
+
## Project files
|
14
|
+
|
15
|
+
There are a couple of prelude files and directories in your project to get you started:
|
16
|
+
|
17
|
+
- `program-graph.rb`: This file defines the default program graph you will be working on
|
18
|
+
- `addon/`: This is the directory where you will place addon resources like the NuSMV executable.
|
File without changes
|
@@ -0,0 +1,103 @@
|
|
1
|
+
####################################################################
|
2
|
+
# Model definition
|
3
|
+
####################################################################
|
4
|
+
|
5
|
+
model :FeelThePain do
|
6
|
+
|
7
|
+
# Define a graph called 'Hand'.
|
8
|
+
graph :Hand do
|
9
|
+
# The hand can be touching the fence or be somewhere else
|
10
|
+
# It starts in 'somewhere' as that state is listed first
|
11
|
+
states :somewhere, :at_fence
|
12
|
+
|
13
|
+
# Transition non-deterministically between those states
|
14
|
+
transition :somewhere => :somewhere
|
15
|
+
transition :somewhere => :at_fence
|
16
|
+
transition :at_fence => :somewhere
|
17
|
+
transition :at_fence => :at_fence
|
18
|
+
end
|
19
|
+
|
20
|
+
# Define another graph called 'PowerSwitch', which also
|
21
|
+
# transitions non-deterministically.
|
22
|
+
graph :PowerSwitch do
|
23
|
+
states :off, :on
|
24
|
+
transition :off => :off
|
25
|
+
transition :off => :on
|
26
|
+
transition :on => :off
|
27
|
+
transition :on => :on
|
28
|
+
end
|
29
|
+
|
30
|
+
graph :Fence do
|
31
|
+
# The fence has no states we are interested in
|
32
|
+
states :exists
|
33
|
+
|
34
|
+
# The fence has a voltage which can go up to 15
|
35
|
+
var :voltage => (0..12), init: 0
|
36
|
+
|
37
|
+
# The voltage increases when the power switch is on
|
38
|
+
transition :exists => :exists do
|
39
|
+
guard "PowerSwitch == on"
|
40
|
+
action "voltage := voltage + 1"
|
41
|
+
end
|
42
|
+
# ..and instantly stops when the switch is off
|
43
|
+
transition :exists => :exists do
|
44
|
+
guard "PowerSwitch == off"
|
45
|
+
action "voltage := 0"
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
graph :Pain do
|
51
|
+
# We can either be in pain or not
|
52
|
+
states :No, :Yes
|
53
|
+
# Using regular variables with string interpolation
|
54
|
+
pain_threshold = 7
|
55
|
+
transition :No => :Yes do
|
56
|
+
# action "voltage := 2"
|
57
|
+
guard "Hand == at_fence && voltage >= #{pain_threshold}"
|
58
|
+
end
|
59
|
+
transition :Yes => :No do
|
60
|
+
guard "Hand == somewhere || voltage < #{pain_threshold}"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
####################################################################
|
65
|
+
# Validity tests
|
66
|
+
####################################################################
|
67
|
+
|
68
|
+
# Specification of validity characteristics regarding the hand.
|
69
|
+
# The 'specify' block serves as a namespace/container for the contained specifications
|
70
|
+
specify "The Hand" do
|
71
|
+
# Define some simple specs using a description text and an LTL expression
|
72
|
+
it "isn't always touching the fence" => :"F Hand == somewhere"
|
73
|
+
it "isn't always away form the fence" => :"F Hand == at_fence"
|
74
|
+
end
|
75
|
+
|
76
|
+
# Specification of validity characteristics regarding the pain
|
77
|
+
specify "The pain" do
|
78
|
+
# Use a regular LTL Formula as the expression
|
79
|
+
it "is felt at some point" => :"F Pain == Yes"
|
80
|
+
# Use a more declarative syntax. This becomes useful for complex expressions
|
81
|
+
# as LTL patterns can be used very easily
|
82
|
+
it "is always felt at some point" => ltl.globally.exists(:"Pain == Yes")
|
83
|
+
|
84
|
+
# Pattern: 'Universality', range: 'after q'
|
85
|
+
it "is felt after the switch is activated" => ltl.after(:"PowerSwitch == on").exists(:"Pain == Yes")
|
86
|
+
# Pattern: 'Absence', range: 'before q'
|
87
|
+
it "is never felt before the switch is activated" => ltl.before(:"PowerSwitch == on").never(:"Pain == Yes")
|
88
|
+
# Pattern: 'Reaction', range: 'global'
|
89
|
+
it "always reacts to the switch being activated" => ltl.globally.reacts(:"PowerSwitch == on", :"Pain == Yes")
|
90
|
+
|
91
|
+
# Define an assumption. That assumption must be true for all contained specs
|
92
|
+
assuming "the switch is never activated" => :"G PowerSwitch == off" do
|
93
|
+
it "is never felt " => :"G Pain == No"
|
94
|
+
end
|
95
|
+
|
96
|
+
# Assumptions can be nested and used with the declarative syntax.
|
97
|
+
assuming "the switch is activated" => ltl.globally.exists(:"PowerSwitch == No") do
|
98
|
+
assuming "the hand never touches the fence" => :"G Hand != at_fence" do
|
99
|
+
it "is never felt " => :"G Pain == No"
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|