From 8cac12b226ac2dc21210b3a3efade50cbb7cd7f8 Mon Sep 17 00:00:00 2001
From: Ezekiel Dohmen <ezekiel.dohmen@ligo.org>
Date: Fri, 1 Apr 2022 13:39:55 -0700
Subject: [PATCH] Adding Noise module parameter that will allow the designer to
 specify a seed in order to re-run with the same RNG, also initializing the
 RNG with a tsc based seen by default. Updating some language around seeding
 the noise part.

---
 src/epics/util/feCodeGen.pl      |  1 +
 src/epics/util/lib/Noise.pm      | 63 ++++++++++++++++++--------------
 src/epics/util/lib/Parameters.pm |  4 ++
 3 files changed, 41 insertions(+), 27 deletions(-)

diff --git a/src/epics/util/feCodeGen.pl b/src/epics/util/feCodeGen.pl
index 16c0cf087..713ba4fb3 100755
--- a/src/epics/util/feCodeGen.pl
+++ b/src/epics/util/feCodeGen.pl
@@ -161,6 +161,7 @@ $dkTimesCalled = 0;
 $remoteGpsPart = 0;
 $remoteGPS = 0;
 $requireIOcnt = 1;
+$noiseGeneratorSeed = 0;
 #Following provide for non standard IOP clock rates
 $adcclock = 64;
 $modelrate = 64;
diff --git a/src/epics/util/lib/Noise.pm b/src/epics/util/lib/Noise.pm
index 59a467d55..bc6877f35 100644
--- a/src/epics/util/lib/Noise.pm
+++ b/src/epics/util/lib/Noise.pm
@@ -13,31 +13,38 @@ $init_code_printed = 0;
 1;
 
 sub partType {
-	return Noise;
+    return Noise;
 }
 
 # Print Epics communication structure into a header file
 # Current part number is passed as first argument
 sub printHeaderStruct {
-        my ($i) = @_;
+    my ($i) = @_;
 }
 
 # Print Epics variable definitions
 # Current part number is passed as first argument
 sub printEpics {
-        my ($i) = @_;
+    my ($i) = @_;
 }
 
 
 # Print variable declarations int front-end file
 # Current part number is passed as first argument
 sub printFrontEndVars  {
-        my ($i) = @_;
-	print ::OUT "static double \L$::xpartName[$i];\n";
-	if ($printed) { return; }
-	print ::OUT << "END";
-static unsigned long noise_seed = 4101842887655102017LL;\n
-static unsigned long noise_u, noise_v, noise_w;
+    my ($i) = @_;
+    print ::OUT "static double \L$::xpartName[$i];\n";
+    if ($printed) { return; }
+
+    if ($::noiseGeneratorSeed != 0) {
+        print ::OUT "static unsigned long noise_seed = " . $::noiseGeneratorSeed . "LL;\n";
+    }
+    else {
+         print ::OUT "static unsigned long noise_seed = 4101842887655102017LL;\n";
+    }
+
+    print ::OUT << "END";
+static unsigned long noise_u = 0, noise_v = 0, noise_w = 0;
 inline unsigned long noise_int64() {
    noise_u = noise_u * 2862933555777941757LL + 7046029254386353087LL;
    noise_v ^= noise_v >> 17; noise_v ^= noise_v << 31; noise_v ^= noise_v >> 8;
@@ -47,10 +54,10 @@ inline unsigned long noise_int64() {
    return (noise_x + noise_v) ^ noise_w;
 }
 inline double noise_doub() { return 5.42101086242752217E-20 * noise_int64(); }
-inline noise_ran(unsigned long j) {
+inline noise_set_seed(unsigned long seed) {
    noise_v = 4101842887655102017LL;
    noise_w = 1;
-   noise_u = j ^ noise_v; noise_int64();
+   noise_u = seed ^ noise_v; noise_int64();
    noise_v = noise_u; noise_int64();
    noise_w = noise_v; noise_int64();
 }
@@ -60,8 +67,8 @@ $printed = 1;
 
 # Check inputs are connected
 sub checkInputConnect {
-        my ($i) = @_;
-        return "";
+    my ($i) = @_;
+    return "";
 }
 
 # Figure out part input code
@@ -69,23 +76,25 @@ sub checkInputConnect {
 # Argument 2 is the input number
 # Returns calculated input code
 sub fromExp {
-        my ($i, $j) = @_;
-        my $from = $::partInNum[$i][$j];
-        return "\L$::xpartName[$from]";
+    my ($i, $j) = @_;
+    my $from = $::partInNum[$i][$j];
+    return "\L$::xpartName[$from]";
 }
 
 # Return front end initialization code
 # Argument 1 is the part number
 # Returns calculated code string
 sub frontEndInitCode {
-	my ($i) = @_;
-	if ($init_code_printed) { return ""; }
-        my $calcExp  =  "\L$::xpartName[$i] = 0;\n";
-	$calcExp    .=  "for (;noise_seed == 4101842887655102017LL;) {\n";
-        $calcExp    .=  "   rdtscl(noise_seed);\n";
-        $calcExp    .=  "}\n";
-	$init_code_printed = 1;
-	return $calcExp;
+    my ($i) = @_;
+    if ($init_code_printed) { return ""; }
+    my $calcExp  =  "\L$::xpartName[$i] = 0;\n";
+    $calcExp    .=  "for (;noise_seed == 4101842887655102017LL;) {\n";
+    $calcExp    .=  "   rdtscl(noise_seed);\n";
+    $calcExp    .=  "}\n";
+    $calcExp    .=  "noise_set_seed(noise_seed);\n";
+
+    $init_code_printed = 1;
+    return $calcExp;
 }
 
 
@@ -93,7 +102,7 @@ sub frontEndInitCode {
 # Argument 1 is the part number
 # Returns calculated code string
 sub frontEndCode {
-	my ($i) = @_;
-        my $calcExp = "// Noise\n";
-        $calcExp .= "\L$::xpartName[$i] = noise_doub();\n";
+    my ($i) = @_;
+    my $calcExp = "// Noise\n";
+    $calcExp .= "\L$::xpartName[$i] = noise_doub();\n";
 }
diff --git a/src/epics/util/lib/Parameters.pm b/src/epics/util/lib/Parameters.pm
index 776f55800..18c91e511 100644
--- a/src/epics/util/lib/Parameters.pm
+++ b/src/epics/util/lib/Parameters.pm
@@ -232,6 +232,10 @@ sub parseParams {
                 {
 				    $::requireIOcnt = $spp[1];
                 }
+                case "noiseGeneratorSeed"
+                {
+                    $::noiseGeneratorSeed = $spp[1];
+                }
                 case "virtualIOP"
                 {
 				    $::virtualiop = $spp[1];
-- 
GitLab