From 278f91e6db50fdb0fb20266401b58e15c15782ae Mon Sep 17 00:00:00 2001 From: jjsuperpower Date: Sat, 17 Sep 2022 09:56:20 -0500 Subject: added random testing --- hdl/config.py | 4 ++- hdl/utils.py | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 91 insertions(+), 2 deletions(-) diff --git a/hdl/config.py b/hdl/config.py index 4761c0a..989a090 100644 --- a/hdl/config.py +++ b/hdl/config.py @@ -5,4 +5,6 @@ ROOT_DIR = os.path.dirname(os.path.abspath(__file__)) HDL_PATH = os.path.join(ROOT_DIR, 'hdl') VERILOG_DIR = os.path.join(ROOT_DIR, 'gen_verilog') CXXRTL_DIR = os.path.join(ROOT_DIR, 'gen_cxxrtl') -VCD_DIR = os.path.join(ROOT_DIR, 'gen_vcd') \ No newline at end of file +VCD_DIR = os.path.join(ROOT_DIR, 'gen_vcd') + +NUM_RAND_TESTS = 250 \ No newline at end of file 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) -- cgit v1.2.3