summaryrefslogtreecommitdiff
path: root/hdl/utils.py
diff options
context:
space:
mode:
Diffstat (limited to 'hdl/utils.py')
-rw-r--r--hdl/utils.py89
1 files changed, 88 insertions, 1 deletions
diff --git a/hdl/utils.py b/hdl/utils.py
index b496356..a6e8de4 100644
--- a/hdl/utils.py
+++ b/hdl/utils.py
@@ -1,13 +1,21 @@
+# general imports
import sys
from inspect import stack # get name of caller function
from typing import Callable
+import random
+
+#hdl specific imports
from amaranth import *
from amaranth import Elaboratable
from amaranth.back import verilog, cxxrtl
from amaranth.sim import Settle, Delay, Simulator
+#custom imports
from hdl.config import *
+# configuration
+random.seed(5498)
+
def cmd(hdl):
'''
@@ -49,4 +57,83 @@ def step(cycles=1):
yield Settle() # settle comb logic before clock
yield # clock edge
yield Settle() # settle comb logic after clock
- yield Delay(5e-7) # used for debugging, change values on neg edge of clock \ No newline at end of file
+ yield Delay(5e-7) # used for debugging, change values on neg edge of clock
+
+def eval():
+ yield Settle()
+ yield Delay(1e-6)
+
+# bits can be integer or Signal
+def rand_bits(bits, sus=None, low=None, high=None):
+ '''
+ Takes number of bits or a Signal and returns a random number
+ if low and high are not specified, the range is 0 to 2**bits - 1
+ If low and high are specified the number of bits is ignored
+ sus (Signed UnSigned) can be 's' or 'u' to force signed or unsigned, default is random
+ sus has no effect if low and high are specified
+ '''
+
+ if isinstance(bits, Signal):
+ bits = bits.width
+
+ if (low == high == None):
+ if sus == 's':
+ low = -2**(bits-1)
+ high = 2**(bits-1) - 1
+ elif sus == 'u':
+ low = 0
+ high = 2**bits - 1
+ else:
+ if random.random() < 0.5:
+ low = 0
+ high = 2**bits - 1
+ else:
+ low = -2**(bits-1)
+ high = 2**(bits-1) - 1
+ else:
+ assert low < high, "low must be less than high"
+ assert low != None, "low must be defined if high is defined"
+ assert high != None, "high must be defined if low is defined"
+
+ return random.randint(low, high)
+
+# bits can be integer or Signal
+def rand_bits_extremes(bits, sus=None):
+ '''
+ Takes number of bits or a Signal and returns a random number with the extremes of the range
+ sus (Signed UnSigned) can be 's' or 'u' to force signed or unsigned, default is random
+ '''
+
+ if isinstance(bits, Signal):
+ bits = bits.width
+
+ if sus == 's':
+ low = -2**(bits-1)
+ high = 2**(bits-1) - 1
+ elif sus == 'u':
+ low = 0
+ high = 2**bits - 1
+ else:
+ if random.random() < 0.5:
+ low = 0
+ high = 2**bits - 1
+ else:
+ low = -2**(bits-1)
+ high = 2**(bits-1) - 1
+
+ choices = [low, high] if low == 0 else [low, 0, high] # if low is 0, don't include it as a choice
+ return random.choice(choices)
+
+
+def rand_bits_mix(bits, low=None, high=None, sus=None, extrem_prob=0.25):
+ '''
+ Take number of bits or a Signal
+ sus determines if the number is signed or unsigned, or both ('s', 'u', or None)
+ Returns a random number with increased likelihood of extremes
+ If low and high are specified the number of bits is ignored
+ The likelyhood of extremes is determined by extrem_prob, default is 0.25
+ '''
+ if random.random() <= extrem_prob:
+ return rand_bits_extremes(bits, sus=sus)
+ else:
+ return rand_bits(bits, sus=sus, low=low, high=high)