Skip to content

Instantly share code, notes, and snippets.

@cfelton
Last active January 26, 2016 12:59
Show Gist options
  • Save cfelton/50cb0fbed5f188fcc1bb to your computer and use it in GitHub Desktop.
Save cfelton/50cb0fbed5f188fcc1bb to your computer and use it in GitHub Desktop.
using constants in myhdl
import argparse
from argparse import Namespace
from myhdl import *
class Constants(object):
def __init__(self, **constargs):
# the const can contain int and str convert all to int
for name, const in constargs.items():
assert isinstance(name, str)
assert isinstance(const, (int, str,))
if isinstance(const, str):
ival = int(const.replace('_', ''), 2)
else:
ival = int(const)
constargs[name] = ival
# create a set, the set of of constants
self._constset = set([cc for np, cc in constargs.items()])
# add the constants to the instance as attributes
for name, const in constargs.items():
self.__dict__[name] = const
self._constants = constargs
def __len__(self):
return len(self._constants)
def __call__(self, val=0):
cmin, cmax = min(self._constset), max(self._constset)
return intbv(val, min=cmin, max=cmax+1)
# global constant used
CPUMODES = Constants(user=0b10000, fiq=0b10001, irq=0b10010)
def enum_cpumodes(modes):
num = 0
if modes == CPUMODES.user:
num = 1
elif modes == CPUMODES.fiq:
num = 2
elif modes == CPUMODES.irq:
num = 3
return num
def mymodes_function(modes, modeenum):
@always_comb
def beh_encode():
modeenum.next = enum_cpumodes(modes)
return beh_encode
def mymodes_module(modes, modeenum):
@always_comb
def beh_encode():
if modes == CPUMODES.user:
modeenum.next = 1
elif modes == CPUMODES.fiq:
modeenum.next = 2
elif modes == CPUMODES.irq:
modeenum.next = 3
return beh_encode
def constant_top(clock, next_mode, sel, modeenum, args):
modes = [Signal(CPUMODES(CPUMODES.user))
for _ in range(2)]
@always(clock.posedge)
def beh_mode_change():
if next_mode:
if modes[sel] == CPUMODES.user:
modes[sel].next = CPUMODES.fiq
elif modes[sel] == CPUMODES.fiq:
modes[sel].next = CPUMODES.irq
elif modes[sel] == CPUMODES.irq:
modes[sel].next = CPUMODES.user
moe = [Signal(intbv(0, min=0, max=len(CPUMODES)+1))
for _ in range(2)]
enum_inst = [None, None]
for ii in range(2):
if args.use_func:
enum_inst[ii] = mymodes_function(modes[ii], moe[ii])
else:
enum_inst[ii] = mymodes_module(modes[ii], moe[ii])
@always_comb
def beh_select():
modeenum.next = moe[sel]
return beh_mode_change, enum_inst, beh_select
def check_modeenum(clock, modeenum, next_mode, sel):
yield clock.posedge
assert modeenum == 1
yield clock.posedge
next_mode.next = True
yield clock.posedge
next_mode.next = False
yield clock.posedge
assert modeenum == 2
yield clock.posedge
sel.next = 1
yield clock.posedge
yield clock.posedge
assert modeenum == 1
def test_func(args=None):
if args is None:
args = Namespace(convert=False, trace=True, use_func=True)
clock = Signal(bool(0))
sel = Signal(bool(0))
next_mode = Signal(bool(0))
modeenum = Signal(intbv(0, min=0, max=len(CPUMODES)+1))
def bench_func():
tbdut = constant_top(clock, next_mode, sel, modeenum, args=args)
@always(delay(5))
def tbclk():
clock.next = not clock
@instance
def tbstim():
yield check_modeenum(clock, modeenum, next_mode, sel)
raise StopSimulation
return tbdut, tbclk, tbstim
if args.trace:
g = traceSignals(bench_func)
else:
g = bench_func()
Simulation(g).run()
if args.convert:
toVerilog(constant_top, clock, next_mode, sel, modeenum, args=args)
toVHDL(constant_top, clock, next_mode, sel, modeenum, args=args)
def test_module(args=None):
if args is None:
args = Namespace(convert=False, trace=True, use_func=False)
clock = Signal(bool(0))
sel = Signal(bool(0))
next_mode = Signal(bool(0))
modeenum = Signal(intbv(0, min=0, max=len(CPUMODES)+1))
def bench_mod():
tbdut = constant_top(clock, next_mode, sel, modeenum, args=args)
@always(delay(5))
def tbclk():
clock.next = not clock
@instance
def tbstim():
yield check_modeenum(clock, modeenum, next_mode, sel)
raise StopSimulation
return tbdut, tbclk, tbstim
if args.trace:
g = traceSignals(bench_mod)
else:
g = bench_mod()
Simulation(g).run()
if args.convert:
toVerilog(constant_top, clock, next_mode, sel, modeenum, args=args)
toVHDL(constant_top, clock, next_mode, sel, modeenum, args=args)
def convert():
modes = Signal(CPUMODES(CPUMODES.user))
modeenum = Signal(intbv(0, min=0, max=len(CPUMODES)+1))
toVHDL(mymodes_module, modes, modeenum)
def get_cli_args():
parser = argparse.ArgumentParser()
# @todo: finish
if __name__ == '__main__':
test_func()
test_module()
@hellow554
Copy link

Awesome. I really like this solution. Next thing would be to add it to the official sources ;)

@cfelton
Copy link
Author

cfelton commented Jan 26, 2016

Updated to use two tests that both create VCD files.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment