pg-verify 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +3 -0
  3. data/Gemfile +10 -0
  4. data/Gemfile.lock +98 -0
  5. data/README.md +29 -0
  6. data/Rakefile +62 -0
  7. data/bin/console +15 -0
  8. data/bin/pg-verify.rb +18 -0
  9. data/bin/setup +8 -0
  10. data/calc.ebnf +21 -0
  11. data/data/config/pg-verify.yml +66 -0
  12. data/data/nusmv.sample.smv +179 -0
  13. data/data/project-template/.gitignore.resource +4 -0
  14. data/data/project-template/.pg-verify.yml +0 -0
  15. data/data/project-template/README.md +18 -0
  16. data/data/project-template/addon/.keep +0 -0
  17. data/data/project-template/program-graph.rb.resource +103 -0
  18. data/devpg +5 -0
  19. data/doc/examples/railroad_crossing.rb +61 -0
  20. data/doc/examples/train-tree.rb +43 -0
  21. data/doc/examples/weidezaun.rb +99 -0
  22. data/doc/examples/weidezaun.txt +29 -0
  23. data/doc/expose/definition.png +0 -0
  24. data/doc/expose/diagram.png +0 -0
  25. data/doc/expose/expose.md +359 -0
  26. data/doc/expose/validity.png +0 -0
  27. data/exe/pg-verify +4 -0
  28. data/integration_tests/ruby_dsl/001_states.rb +10 -0
  29. data/integration_tests/ruby_dsl/002_transitions.rb +10 -0
  30. data/integration_tests/ruby_dsl/003_actions.rb +14 -0
  31. data/integration_tests/ruby_dsl/004_guards.rb +18 -0
  32. data/integration_tests/ruby_dsl/005_variables.rb +16 -0
  33. data/integration_tests/ruby_dsl/006_state_variables.rb +26 -0
  34. data/integration_tests/ruby_dsl/007_variable_initialization.rb +28 -0
  35. data/integration_tests/ruby_dsl/008_state_initialization.rb +19 -0
  36. data/integration_tests/ruby_dsl/009_shared_variables.rb +26 -0
  37. data/integration_tests/ruby_dsl/010_complex_guards.rb +18 -0
  38. data/integration_tests/ruby_dsl/011_complex_actions.rb +16 -0
  39. data/integration_tests/ruby_dsl/012_error_components.rb +9 -0
  40. data/integration_tests/ruby_dsl/013_hazards.rb +25 -0
  41. data/integration_tests/ruby_dsl/014_tau_transitions.rb +26 -0
  42. data/integration_tests/ruby_dsl/015_basic_dcca.rb +19 -0
  43. data/integration_tests/ruby_dsl/016_pressure_tank.rb +146 -0
  44. data/lib/pg-verify/cli/cli.rb +235 -0
  45. data/lib/pg-verify/core/cmd_runner.rb +151 -0
  46. data/lib/pg-verify/core/core.rb +38 -0
  47. data/lib/pg-verify/core/extensions/array_extensions.rb +11 -0
  48. data/lib/pg-verify/core/extensions/enumerable_extensions.rb +19 -0
  49. data/lib/pg-verify/core/extensions/nil_extensions.rb +7 -0
  50. data/lib/pg-verify/core/extensions/string_extensions.rb +84 -0
  51. data/lib/pg-verify/core/shell/colorizer.rb +136 -0
  52. data/lib/pg-verify/core/shell/shell.rb +0 -0
  53. data/lib/pg-verify/core/util.rb +146 -0
  54. data/lib/pg-verify/doctor/doctor.rb +180 -0
  55. data/lib/pg-verify/ebnf_parser/ast.rb +31 -0
  56. data/lib/pg-verify/ebnf_parser/ebnf_parser.rb +26 -0
  57. data/lib/pg-verify/ebnf_parser/expression_parser.rb +177 -0
  58. data/lib/pg-verify/ebnf_parser/expression_parser2.rb +422 -0
  59. data/lib/pg-verify/ebnf_parser/expressions.ebnf +33 -0
  60. data/lib/pg-verify/ebnf_parser/expressions.peg +52 -0
  61. data/lib/pg-verify/ebnf_parser/parser_result.rb +26 -0
  62. data/lib/pg-verify/interpret/component_context.rb +125 -0
  63. data/lib/pg-verify/interpret/graph_context.rb +85 -0
  64. data/lib/pg-verify/interpret/interpret.rb +142 -0
  65. data/lib/pg-verify/interpret/pg_script.rb +72 -0
  66. data/lib/pg-verify/interpret/spec/ltl_builder.rb +90 -0
  67. data/lib/pg-verify/interpret/spec/spec_context.rb +32 -0
  68. data/lib/pg-verify/interpret/spec/spec_set_context.rb +67 -0
  69. data/lib/pg-verify/interpret/transition_context.rb +55 -0
  70. data/lib/pg-verify/model/allocation_set.rb +28 -0
  71. data/lib/pg-verify/model/assignment.rb +34 -0
  72. data/lib/pg-verify/model/component.rb +40 -0
  73. data/lib/pg-verify/model/dcca/hazard.rb +16 -0
  74. data/lib/pg-verify/model/dcca.rb +67 -0
  75. data/lib/pg-verify/model/expression.rb +106 -0
  76. data/lib/pg-verify/model/graph.rb +58 -0
  77. data/lib/pg-verify/model/model.rb +10 -0
  78. data/lib/pg-verify/model/parsed_expression.rb +77 -0
  79. data/lib/pg-verify/model/simulation/trace.rb +43 -0
  80. data/lib/pg-verify/model/simulation/variable_state.rb +23 -0
  81. data/lib/pg-verify/model/source_location.rb +45 -0
  82. data/lib/pg-verify/model/specs/spec.rb +44 -0
  83. data/lib/pg-verify/model/specs/spec_result.rb +25 -0
  84. data/lib/pg-verify/model/specs/spec_set.rb +43 -0
  85. data/lib/pg-verify/model/specs/specification.rb +50 -0
  86. data/lib/pg-verify/model/transition.rb +41 -0
  87. data/lib/pg-verify/model/validation/assignment_to_state_variable_validation.rb +26 -0
  88. data/lib/pg-verify/model/validation/empty_state_set_validation.rb +18 -0
  89. data/lib/pg-verify/model/validation/errors.rb +119 -0
  90. data/lib/pg-verify/model/validation/foreign_assignment_validation.rb +30 -0
  91. data/lib/pg-verify/model/validation/unknown_token_validation.rb +35 -0
  92. data/lib/pg-verify/model/validation/validation.rb +23 -0
  93. data/lib/pg-verify/model/variable.rb +47 -0
  94. data/lib/pg-verify/model/variable_set.rb +84 -0
  95. data/lib/pg-verify/nusmv/nusmv.rb +23 -0
  96. data/lib/pg-verify/nusmv/runner.rb +124 -0
  97. data/lib/pg-verify/puml/puml.rb +23 -0
  98. data/lib/pg-verify/shell/loading/line_animation.rb +36 -0
  99. data/lib/pg-verify/shell/loading/loading_animation.rb +80 -0
  100. data/lib/pg-verify/shell/loading/loading_prompt.rb +43 -0
  101. data/lib/pg-verify/shell/loading/no_animation.rb +20 -0
  102. data/lib/pg-verify/shell/shell.rb +30 -0
  103. data/lib/pg-verify/simulation/simulation.rb +7 -0
  104. data/lib/pg-verify/simulation/simulator.rb +90 -0
  105. data/lib/pg-verify/simulation/state.rb +53 -0
  106. data/lib/pg-verify/transform/hash_transformation.rb +104 -0
  107. data/lib/pg-verify/transform/nusmv_transformation.rb +261 -0
  108. data/lib/pg-verify/transform/puml_transformation.rb +89 -0
  109. data/lib/pg-verify/transform/transform.rb +8 -0
  110. data/lib/pg-verify/version.rb +5 -0
  111. data/lib/pg-verify.rb +47 -0
  112. data/pg-verify.gemspec +38 -0
  113. data/sig/pg-verify.rbs +4 -0
  114. 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
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ # Specify your gem's dependencies in pg-verify.gemspec
6
+ gemspec
7
+
8
+ gem "rake", "~> 13.0"
9
+
10
+ gem "rspec", "~> 3.0"
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
@@ -0,0 +1,18 @@
1
+ require "bundler/setup"
2
+ require 'pg-verify'
3
+
4
+ module PgVerify
5
+
6
+ class PgVerifyCLI
7
+
8
+ def run()
9
+ begin
10
+ Cli::BaseCommand.start()
11
+ rescue Core::Error => e
12
+ puts e.to_formatted()
13
+ end
14
+ end
15
+
16
+ end
17
+
18
+ end
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
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)
@@ -0,0 +1,4 @@
1
+ .pg-work/
2
+ addon/
3
+ out/
4
+ .vscode
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
data/devpg ADDED
@@ -0,0 +1,5 @@
1
+ #!/bin/sh
2
+
3
+ # Simple wrapper to run pg-verify during development.
4
+
5
+ ruby -Ilib ./exe/pg-verify "$@"