[prim] Make SECDED prim generation deterministic
There's no need for this to be parameterised by some seed and we're
going to need to build software with the right ECC constants (for ROM
image generation), so let's just pick a golden seed.
Signed-off-by: Rupert Swarbrick <rswarbrick@lowrisc.org>
diff --git a/util/design/secded_gen.py b/util/design/secded_gen.py
index 4a32f64..0178f2e 100755
--- a/util/design/secded_gen.py
+++ b/util/design/secded_gen.py
@@ -29,6 +29,10 @@
# secded configurations
SECDED_CFG_FILE = "util/design/data/secded_cfg.hjson"
+# The seed we use to initialise the PRNG when running the randomised algorithm
+# to choose constants for Hsiao codes.
+_RND_SEED = 123
+
def min_paritysize(k):
# SECDED --> Hamming distance 'd': 4
@@ -192,12 +196,6 @@
def verify(cfgs):
error = 0
-
- # Check that the provided seed is 32-bit int
- if (cfgs['seed'].bit_length() > 31):
- error += 1
- log.error("Seed {} must be a 32-bit integer".format(cfgs['seed']))
-
for cfg in cfgs['cfgs']:
if (cfg['k'] <= 1 or cfg['k'] > 120):
error += 1
@@ -223,7 +221,19 @@
return error
-def generate(cfgs, args, seed):
+def gen_code(codetype, k, m):
+ # The hsiao_code generator uses (pseudo)random values to pick good ECC
+ # constants. Rather than exposing the seed, we pick a fixed one here to
+ # ensure everything stays stable in future.
+ old_rnd_state = random.getstate()
+ random.seed(_RND_SEED)
+ try:
+ return globals()["_{}_code".format(codetype)](k, m)
+ finally:
+ random.setstate(old_rnd_state)
+
+
+def generate(cfgs, args):
pkg_out_str = ""
pkg_type_str = ""
for cfg in cfgs['cfgs']:
@@ -233,13 +243,10 @@
n = k + m
codetype = cfg['code_type']
suffix = CODE_OPTIONS[codetype]
- codes = []
-
- # update value based on target selection
- codes = globals()["{}_code".format(codetype)](cfg['k'], cfg['m'])
+ codes = gen_code(codetype, k, m)
# write out rtl files
- write_enc_dec_files(n, k, m, seed, codes, suffix, args.outdir, codetype)
+ write_enc_dec_files(n, k, m, codes, suffix, args.outdir, codetype)
# write out package typedefs
pkg_type_str += print_pkg_types(n, k, m, codes, suffix, codetype)
@@ -251,13 +258,13 @@
# write out package file
full_pkg_str = pkg_type_str + pkg_out_str
- write_pkg_file(seed, args.outdir, full_pkg_str)
+ write_pkg_file(args.outdir, full_pkg_str)
# k = data bits
# m = parity bits
# generate hsiao code
-def hsiao_code(k, m):
+def _hsiao_code(k, m):
# using itertools combinations, generate odd number of 1 in a row
required_row = k # k rows are needed, decreasing everytime when it acquite
@@ -344,7 +351,7 @@
# k = data bits
# m = parity bits
# generate hamming code
-def hamming_code(k, m):
+def _hamming_code(k, m):
n = k + m
@@ -385,28 +392,26 @@
return codes
-def write_pkg_file(s, outdir, pkg_str):
-
+def write_pkg_file(outdir, pkg_str):
with open(outdir + "/" + "prim_secded_pkg.sv", "w") as f:
- outstr = '''{}// SECDED Encoder generated by
-// util/design/secded_gen.py -s {} from {}
+ outstr = '''{}// SECDED package generated by
+// util/design/secded_gen.py from {}
package prim_secded_pkg;
{}
endpackage
-'''.format(COPYRIGHT, s, SECDED_CFG_FILE, pkg_str)
+'''.format(COPYRIGHT, SECDED_CFG_FILE, pkg_str)
f.write(outstr)
-def write_enc_dec_files(n, k, m, s, codes, suffix, outdir, codetype):
+def write_enc_dec_files(n, k, m, codes, suffix, outdir, codetype):
enc_out = print_enc(n, k, m, codes)
module_name = "prim_secded%s_%d_%d" % (suffix, n, k)
with open(outdir + "/" + module_name + "_enc.sv", "w") as f:
- outstr = '''{}// SECDED Encoder generated by
-// util/design/secded_gen.py -m {} -k {} -s {} -c {}
+ outstr = '''{}// SECDED encoder generated by util/design/secded_gen.py
module {}_enc (
input [{}:0] in,
@@ -417,15 +422,13 @@
{} end
endmodule : {}_enc
-'''.format(COPYRIGHT, m, k, s, codetype, module_name, (k - 1), (n - 1),
- enc_out, module_name)
+'''.format(COPYRIGHT, module_name, (k - 1), (n - 1), enc_out, module_name)
f.write(outstr)
dec_out = print_dec(n, k, m, codes, codetype)
with open(outdir + "/" + module_name + "_dec.sv", "w") as f:
- outstr = '''{}// SECDED Decoder generated by
-// util/design/secded_gen.py -m {} -k {} -s {} -c {}
+ outstr = '''{}// SECDED decoder generated by util/design/secded_gen.py
module {}_dec (
input [{}:0] in,
@@ -436,8 +439,8 @@
{}
endmodule : {}_dec
-'''.format(COPYRIGHT, m, k, s, codetype, module_name, (n - 1), (k - 1),
- (m - 1), dec_out, module_name)
+'''.format(COPYRIGHT, module_name, (n - 1), (k - 1), (m - 1),
+ dec_out, module_name)
f.write(outstr)
@@ -575,10 +578,6 @@
description='''This tool generates Single Error Correction Double Error
Detection(SECDED) encoder and decoder modules in SystemVerilog.
''')
- parser.add_argument('-s',
- type=int,
- metavar='<seed>',
- help='Custom seed for RNG.')
parser.add_argument('--no_fpv',
action='store_true',
help='Do not generate FPV testbench.')
@@ -611,15 +610,8 @@
if (error):
exit(1)
- # If no seed is provided from the command line, use the seed provided in
- # data/secded_cfg.hjson by default, such that runs of this script can be
- # reproduced.
- random.seed()
- rand_seed = config['seed'] if args.s is None else args.s
- random.seed(rand_seed)
-
# Generate outputs
- generate(config, args, rand_seed)
+ generate(config, args)
if __name__ == "__main__":