- Minor codebase clean-up - Slight reorganisation of examples + tests so that we don't break stuff by accident - CI tests
89 lines
3.0 KiB
Python
89 lines
3.0 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Generator for the Binary Counter (BC) benchmark.
|
|
|
|
Produces a reaction system modelling an N-bit binary counter
|
|
with increment and decrement operations controlled via context
|
|
entities. Generates one of four RSCTL properties.
|
|
|
|
NOTE: generates old-syntax input (context-entities, initial-contexts,
|
|
rsctl-property) which is not compatible with the current parser.
|
|
"""
|
|
|
|
import argparse
|
|
|
|
K = 8 # constant used by property 3
|
|
|
|
|
|
def generate(n, prop):
|
|
out = "reactions {\n"
|
|
|
|
# (1) no dec, no inc: bits persist
|
|
out += "\t# (1) no decrement, no increment\n"
|
|
for j in range(n):
|
|
out += "\t{{{{p{j}}},{{dec,inc}} -> {{p{j}}}}};\n".format(j=j)
|
|
|
|
# (2) increment operation
|
|
out += "\n\t# (2) increment operation\n"
|
|
out += "\t{{inc},{dec,p0} -> {p0}};\n"
|
|
for j in range(1, n):
|
|
bits = ",".join("p" + str(k) for k in range(j))
|
|
out += "\t{{{{inc,{bits}}},{{dec,p{j}}} -> {{p{j}}}}};\n".format(bits=bits, j=j)
|
|
|
|
out += "\n\t# the more significant bits remain (inc)\n"
|
|
for j in range(n):
|
|
for k in range(j + 1, n):
|
|
out += "\t{{{{inc,p{k}}},{{dec,p{j}}} -> {{p{k}}}}};\n".format(j=j, k=k)
|
|
|
|
# (3) decrement operation
|
|
out += "\n\t# (3) decrement operation\n"
|
|
for j in range(n):
|
|
bits = ",".join("p" + str(k) for k in range(j + 1))
|
|
out += "\t{{{{dec}},{{inc,{bits}}} -> {{p{j}}}}};\n".format(bits=bits, j=j)
|
|
|
|
out += "\n\t# the more significant bits remain (dec)\n"
|
|
for j in range(n):
|
|
for k in range(j + 1, n):
|
|
out += "\t{{{{dec,p{j},p{k}}},{{inc}} -> {{p{k}}}}};\n".format(j=j, k=k)
|
|
|
|
out += "}\n\n"
|
|
out += "context-entities { inc,dec }\n"
|
|
out += "initial-contexts { {} }\n"
|
|
|
|
if prop == 1:
|
|
all_neg = " AND ".join("~p" + str(i) for i in range(n))
|
|
all_pos = " AND ".join("p" + str(i) for i in range(n))
|
|
out += "rsctl-property {{ AG(({}) IMPLIES E[{{inc}},{{dec}}]F({})) }}\n".format(
|
|
all_neg, all_pos)
|
|
elif prop == 2:
|
|
all_pos = " AND ".join("p" + str(i) for i in range(n))
|
|
all_neg = " AND ".join("~p" + str(i) for i in range(n))
|
|
out += "rsctl-property {{ AG(({}) IMPLIES A[{{inc}}]X({})) }}\n".format(
|
|
all_pos, all_neg)
|
|
elif prop == 3:
|
|
parts = ["p" + str(i) for i in range(n - K)]
|
|
parts += ["~p" + str(i) for i in range(n - K, n)]
|
|
out += "rsctl-property {{ E[{{inc}}]F({}) }}\n".format(" AND ".join(parts))
|
|
elif prop == 4:
|
|
out += "rsctl-property {{ AG( p{} IMPLIES EF ~p{} ) }}\n".format(n - 1, n - 1)
|
|
|
|
return out
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description=__doc__,
|
|
formatter_class=argparse.RawDescriptionHelpFormatter)
|
|
parser.add_argument("n", type=int, help="number of bits")
|
|
parser.add_argument("property", type=int, choices=[1, 2, 3, 4],
|
|
help="property to generate (1-4)")
|
|
args = parser.parse_args()
|
|
|
|
if args.property == 3 and args.n < K + 1:
|
|
parser.error("n must be >= {} for property 3".format(K + 1))
|
|
|
|
print(generate(args.n, args.property))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|