pg-verify 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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 "$@"