Skip to content

Instantly share code, notes, and snippets.

@cfelton
Last active January 26, 2016 12:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • 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()
@josyb
Copy link

josyb commented Jan 21, 2016

How about using a dict in stead of a tuple of tuples?

CPUMODES = Constants({'user': 0b10000, 'fiq': 0b10001, 'irq': 0b10010})

@cfelton
Copy link
Author

cfelton commented Jan 21, 2016

@josyb I updated it before I saw your comment to use **kwargs

CPUMODES = Constants(user=0b10000, fiq=0b10001, irq=0b10010)

I think I did it the first way because the OP mentioned something like it ...

@josyb
Copy link

josyb commented Jan 21, 2016

@cfelton I like that solution as well ;)

@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