mirror of
https://github.com/enjoy-digital/litex.git
synced 2025-01-04 09:52:26 -05:00
move pytholite to separate repos
This commit is contained in:
parent
c824379878
commit
beeaefccea
10 changed files with 0 additions and 1105 deletions
|
@ -1,46 +0,0 @@
|
||||||
from migen.flow.network import *
|
|
||||||
from migen.flow.transactions import *
|
|
||||||
from migen.actorlib.sim import *
|
|
||||||
from migen.pytholite.compiler import Pytholite
|
|
||||||
from migen.sim.generic import run_simulation
|
|
||||||
from migen.fhdl import verilog
|
|
||||||
|
|
||||||
layout = [("r", 32)]
|
|
||||||
|
|
||||||
def number_gen(n):
|
|
||||||
for i in range(n):
|
|
||||||
yield Token("result", {"r": i})
|
|
||||||
|
|
||||||
class SimNumberGen(SimActor):
|
|
||||||
def __init__(self):
|
|
||||||
self.result = Source(layout)
|
|
||||||
SimActor.__init__(self, number_gen(5))
|
|
||||||
|
|
||||||
def run_ng_sim(ng):
|
|
||||||
g = DataFlowGraph()
|
|
||||||
d = Dumper(layout)
|
|
||||||
g.add_connection(ng, d)
|
|
||||||
|
|
||||||
c = CompositeActor(g)
|
|
||||||
run_simulation(c, ncycles=20)
|
|
||||||
|
|
||||||
def make_ng_pytholite():
|
|
||||||
ng_pytholite = Pytholite(number_gen, 5)
|
|
||||||
ng_pytholite.result = Source(layout)
|
|
||||||
ng_pytholite.finalize()
|
|
||||||
return ng_pytholite
|
|
||||||
|
|
||||||
def main():
|
|
||||||
print("Simulating native Python:")
|
|
||||||
ng_native = SimNumberGen()
|
|
||||||
run_ng_sim(ng_native)
|
|
||||||
|
|
||||||
print("Simulating Pytholite:")
|
|
||||||
ng_pytholite = make_ng_pytholite()
|
|
||||||
run_ng_sim(ng_pytholite)
|
|
||||||
|
|
||||||
print("Converting Pytholite to Verilog:")
|
|
||||||
ng_pytholite = make_ng_pytholite()
|
|
||||||
print(verilog.convert(ng_pytholite))
|
|
||||||
|
|
||||||
main()
|
|
|
@ -1,67 +0,0 @@
|
||||||
from migen.flow.network import *
|
|
||||||
from migen.flow.transactions import *
|
|
||||||
from migen.actorlib.sim import Dumper
|
|
||||||
from migen.bus import wishbone
|
|
||||||
from migen.bus.transactions import *
|
|
||||||
from migen.genlib.ioo import UnifiedIOSimulation
|
|
||||||
from migen.pytholite.transel import Register
|
|
||||||
from migen.pytholite.compiler import Pytholite
|
|
||||||
from migen.sim.generic import run_simulation
|
|
||||||
from migen.fhdl.std import *
|
|
||||||
from migen.fhdl import verilog
|
|
||||||
|
|
||||||
layout = [("r", 32)]
|
|
||||||
|
|
||||||
def gen():
|
|
||||||
ds = Register(32)
|
|
||||||
for i in range(3):
|
|
||||||
r = TRead(i, busname="mem")
|
|
||||||
yield r
|
|
||||||
ds.store = r.data
|
|
||||||
yield Token("result", {"r": ds})
|
|
||||||
for i in range(5):
|
|
||||||
r = TRead(i, busname="wb")
|
|
||||||
yield r
|
|
||||||
ds.store = r.data
|
|
||||||
yield Token("result", {"r": ds})
|
|
||||||
|
|
||||||
class SlaveModel(wishbone.TargetModel):
|
|
||||||
def read(self, address):
|
|
||||||
return address + 4
|
|
||||||
|
|
||||||
class TestBench(Module):
|
|
||||||
def __init__(self, ng):
|
|
||||||
g = DataFlowGraph()
|
|
||||||
d = Dumper(layout)
|
|
||||||
g.add_connection(ng, d)
|
|
||||||
|
|
||||||
self.submodules.slave = wishbone.Target(SlaveModel())
|
|
||||||
self.submodules.intercon = wishbone.InterconnectPointToPoint(ng.wb, self.slave.bus)
|
|
||||||
self.submodules.ca = CompositeActor(g)
|
|
||||||
|
|
||||||
def run_ng_sim(ng):
|
|
||||||
run_simulation(TestBench(ng), ncycles=50)
|
|
||||||
|
|
||||||
def add_interfaces(obj):
|
|
||||||
obj.result = Source(layout)
|
|
||||||
obj.wb = wishbone.Interface()
|
|
||||||
obj.mem = Memory(32, 3, init=[42, 37, 81])
|
|
||||||
obj.finalize()
|
|
||||||
|
|
||||||
def main():
|
|
||||||
print("Simulating native Python:")
|
|
||||||
ng_native = UnifiedIOSimulation(gen())
|
|
||||||
add_interfaces(ng_native)
|
|
||||||
run_ng_sim(ng_native)
|
|
||||||
|
|
||||||
print("Simulating Pytholite:")
|
|
||||||
ng_pytholite = Pytholite(gen)
|
|
||||||
add_interfaces(ng_pytholite)
|
|
||||||
run_ng_sim(ng_pytholite)
|
|
||||||
|
|
||||||
print("Converting Pytholite to Verilog:")
|
|
||||||
ng_pytholite = Pytholite(gen)
|
|
||||||
add_interfaces(ng_pytholite)
|
|
||||||
print(verilog.convert(ng_pytholite))
|
|
||||||
|
|
||||||
main()
|
|
|
@ -1,79 +0,0 @@
|
||||||
from migen.util.misc import xdir
|
|
||||||
from migen.fhdl.std import *
|
|
||||||
from migen.flow.actor import *
|
|
||||||
from migen.flow.actor import _Endpoint
|
|
||||||
from migen.flow.transactions import *
|
|
||||||
from migen.actorlib.sim import TokenExchanger
|
|
||||||
from migen.bus import wishbone, memory
|
|
||||||
from migen.bus.transactions import *
|
|
||||||
|
|
||||||
class UnifiedIOObject(Module):
|
|
||||||
def do_finalize(self):
|
|
||||||
if self.get_dataflow():
|
|
||||||
self.busy = Signal()
|
|
||||||
self.specials += set(v for k, v in xdir(self, True) if isinstance(v, Memory))
|
|
||||||
|
|
||||||
def get_dataflow(self):
|
|
||||||
return dict((k, v) for k, v in xdir(self, True) if isinstance(v, _Endpoint))
|
|
||||||
|
|
||||||
def get_buses(self):
|
|
||||||
return dict((k, v) for k, v in xdir(self, True) if isinstance(v, (wishbone.Interface, Memory)))
|
|
||||||
|
|
||||||
(_WAIT_COMPLETE, _WAIT_POLL) = range(2)
|
|
||||||
|
|
||||||
class UnifiedIOSimulation(UnifiedIOObject):
|
|
||||||
def __init__(self, generator):
|
|
||||||
self.generator = generator
|
|
||||||
|
|
||||||
def do_finalize(self):
|
|
||||||
UnifiedIOObject.do_finalize(self)
|
|
||||||
callers = []
|
|
||||||
self.busname_to_caller_id = {}
|
|
||||||
if self.get_dataflow():
|
|
||||||
callers.append(TokenExchanger(self.dispatch_g(0), self))
|
|
||||||
for k, v in self.get_buses().items():
|
|
||||||
caller_id = len(callers)
|
|
||||||
self.busname_to_caller_id[k] = caller_id
|
|
||||||
g = self.dispatch_g(caller_id)
|
|
||||||
if isinstance(v, wishbone.Interface):
|
|
||||||
caller = wishbone.Initiator(g, v)
|
|
||||||
elif isinstance(v, Memory):
|
|
||||||
caller = memory.Initiator(g, v)
|
|
||||||
callers.append(caller)
|
|
||||||
self.submodules += callers
|
|
||||||
|
|
||||||
self.dispatch_state = _WAIT_COMPLETE
|
|
||||||
self.dispatch_caller = 0
|
|
||||||
self.pending_transaction = None
|
|
||||||
|
|
||||||
def identify_transaction(self, t):
|
|
||||||
if isinstance(t, Token):
|
|
||||||
return 0
|
|
||||||
elif isinstance(t, TRead) or isinstance(t, TWrite):
|
|
||||||
if t.busname is None:
|
|
||||||
if len(self.busname_to_caller_id) != 1:
|
|
||||||
raise TypeError
|
|
||||||
else:
|
|
||||||
return list(self.busname_to_caller_id.values())[0]
|
|
||||||
else:
|
|
||||||
return self.busname_to_caller_id[t.busname]
|
|
||||||
else:
|
|
||||||
raise TypeError
|
|
||||||
|
|
||||||
def dispatch_g(self, caller_id):
|
|
||||||
while True:
|
|
||||||
if self.dispatch_state == _WAIT_COMPLETE and self.dispatch_caller == caller_id:
|
|
||||||
transaction = next(self.generator)
|
|
||||||
tr_cid = self.identify_transaction(transaction)
|
|
||||||
self.dispatch_caller = tr_cid
|
|
||||||
if tr_cid == caller_id:
|
|
||||||
yield transaction
|
|
||||||
else:
|
|
||||||
self.pending_transaction = transaction
|
|
||||||
self.dispatch_state = _WAIT_POLL
|
|
||||||
yield None
|
|
||||||
elif self.dispatch_state == _WAIT_POLL and self.dispatch_caller == caller_id:
|
|
||||||
self.dispatch_state = _WAIT_COMPLETE
|
|
||||||
yield self.pending_transaction
|
|
||||||
else:
|
|
||||||
yield None
|
|
|
@ -1,318 +0,0 @@
|
||||||
import inspect
|
|
||||||
import ast
|
|
||||||
from collections import OrderedDict
|
|
||||||
|
|
||||||
from migen.util.misc import xdir
|
|
||||||
from migen.fhdl.structure import *
|
|
||||||
from migen.fhdl.visit import TransformModule
|
|
||||||
from migen.fhdl.specials import Memory
|
|
||||||
from migen.genlib.ioo import UnifiedIOObject
|
|
||||||
from migen.pytholite.reg import *
|
|
||||||
from migen.pytholite.expr import *
|
|
||||||
from migen.pytholite import transel
|
|
||||||
from migen.pytholite.io import gen_io
|
|
||||||
from migen.pytholite.util import *
|
|
||||||
|
|
||||||
def _is_name_used(node, name):
|
|
||||||
for n in ast.walk(node):
|
|
||||||
if isinstance(n, ast.Name) and n.id == name:
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
def _make_function_args_dict(undefined, symdict, args, defaults):
|
|
||||||
d = OrderedDict()
|
|
||||||
for argument in args:
|
|
||||||
d[argument.arg] = undefined
|
|
||||||
for default, argname in zip(defaults, reversed(list(d.keys()))):
|
|
||||||
default_val = eval_ast(default, symdict)
|
|
||||||
d[argname] = default_val
|
|
||||||
return d
|
|
||||||
|
|
||||||
def _process_function_args(symdict, function_def, args, kwargs):
|
|
||||||
defargs = function_def.args
|
|
||||||
undefined = object()
|
|
||||||
|
|
||||||
ad_positional = _make_function_args_dict(undefined, symdict, defargs.args, defargs.defaults)
|
|
||||||
vararg_name = defargs.vararg
|
|
||||||
kwarg_name = defargs.kwarg
|
|
||||||
ad_kwonly = _make_function_args_dict(undefined, symdict, defargs.kwonlyargs, defargs.kw_defaults)
|
|
||||||
|
|
||||||
# grab argument values
|
|
||||||
current_argvalue = iter(args)
|
|
||||||
try:
|
|
||||||
for argname in ad_positional.keys():
|
|
||||||
ad_positional[argname] = next(current_argvalue)
|
|
||||||
except StopIteration:
|
|
||||||
pass
|
|
||||||
vararg = tuple(current_argvalue)
|
|
||||||
|
|
||||||
kwarg = dict()
|
|
||||||
for k, v in kwargs.items():
|
|
||||||
if k in ad_positional:
|
|
||||||
ad_positional[k] = v
|
|
||||||
elif k in ad_kwonly:
|
|
||||||
ad_kwonly[k] = v
|
|
||||||
else:
|
|
||||||
kwarg[k] = v
|
|
||||||
|
|
||||||
# check
|
|
||||||
undefined_pos = [k for k, v in ad_positional.items() if v is undefined]
|
|
||||||
if undefined_pos:
|
|
||||||
formatted = " and ".join("'" + k + "'" for k in undefined_pos)
|
|
||||||
raise TypeError("Missing required positional arguments: " + formatted)
|
|
||||||
if vararg and vararg_name is None:
|
|
||||||
raise TypeError("Function takes {} positional arguments but {} were given".format(len(ad_positional),
|
|
||||||
len(ad_positional) + len(vararg)))
|
|
||||||
ad_kwonly = [k for k, v in ad_positional.items() if v is undefined]
|
|
||||||
if undefined_pos:
|
|
||||||
formatted = " and ".join("'" + k + "'" for k in undefined_pos)
|
|
||||||
raise TypeError("Missing required keyword-only arguments: " + formatted)
|
|
||||||
if kwarg and kwarg_name is None:
|
|
||||||
formatted = " and ".join("'" + k + "'" for k in kwarg.keys())
|
|
||||||
raise TypeError("Got unexpected keyword arguments: " + formatted)
|
|
||||||
|
|
||||||
# update symdict
|
|
||||||
symdict.update(ad_positional)
|
|
||||||
if vararg_name is not None:
|
|
||||||
symdict[vararg_name] = vararg
|
|
||||||
symdict.update(ad_kwonly)
|
|
||||||
if kwarg_name is not None:
|
|
||||||
symdict[kwarg_name] = kwarg
|
|
||||||
|
|
||||||
class _Compiler:
|
|
||||||
def __init__(self, ioo, symdict, registers):
|
|
||||||
self.ioo = ioo
|
|
||||||
self.symdict = symdict
|
|
||||||
self.registers = registers
|
|
||||||
self.ec = ExprCompiler(self.symdict)
|
|
||||||
|
|
||||||
def visit_top(self, node, args, kwargs):
|
|
||||||
if isinstance(node, ast.Module) \
|
|
||||||
and len(node.body) == 1 \
|
|
||||||
and isinstance(node.body[0], ast.FunctionDef):
|
|
||||||
function_def = node.body[0]
|
|
||||||
_process_function_args(self.symdict, function_def, args, kwargs)
|
|
||||||
states, exit_states = self.visit_block(function_def.body)
|
|
||||||
return states
|
|
||||||
else:
|
|
||||||
raise NotImplementedError
|
|
||||||
|
|
||||||
# blocks and statements
|
|
||||||
def visit_block(self, statements):
|
|
||||||
sa = StateAssembler()
|
|
||||||
statements = iter(statements)
|
|
||||||
statement = None
|
|
||||||
while True:
|
|
||||||
if statement is None:
|
|
||||||
try:
|
|
||||||
statement = next(statements)
|
|
||||||
except StopIteration:
|
|
||||||
return sa.ret()
|
|
||||||
if isinstance(statement, ast.Assign):
|
|
||||||
# visit_assign can recognize a I/O pattern, consume several
|
|
||||||
# statements from the iterator and return the first statement
|
|
||||||
# that is not part of the I/O pattern anymore.
|
|
||||||
statement = self.visit_assign(sa, statement, statements)
|
|
||||||
else:
|
|
||||||
if isinstance(statement, ast.If):
|
|
||||||
self.visit_if(sa, statement)
|
|
||||||
elif isinstance(statement, ast.While):
|
|
||||||
self.visit_while(sa, statement)
|
|
||||||
elif isinstance(statement, ast.For):
|
|
||||||
self.visit_for(sa, statement)
|
|
||||||
elif isinstance(statement, ast.Expr):
|
|
||||||
self.visit_expr_statement(sa, statement)
|
|
||||||
else:
|
|
||||||
raise NotImplementedError
|
|
||||||
statement = None
|
|
||||||
|
|
||||||
def visit_assign(self, sa, node, statements):
|
|
||||||
if isinstance(node.value, ast.Call):
|
|
||||||
is_special = False
|
|
||||||
try:
|
|
||||||
value = self.ec.visit_expr_call(node.value)
|
|
||||||
except NotImplementedError:
|
|
||||||
is_special = True
|
|
||||||
if is_special:
|
|
||||||
return self.visit_assign_special(sa, node, statements)
|
|
||||||
else:
|
|
||||||
value = self.ec.visit_expr(node.value)
|
|
||||||
if isinstance(value, (int, bool, Value)):
|
|
||||||
r = []
|
|
||||||
for target in node.targets:
|
|
||||||
if isinstance(target, ast.Attribute) and target.attr == "store":
|
|
||||||
treg = target.value
|
|
||||||
if isinstance(treg, ast.Name):
|
|
||||||
r.append(self.symdict[treg.id].load(value))
|
|
||||||
else:
|
|
||||||
raise NotImplementedError
|
|
||||||
else:
|
|
||||||
raise NotImplementedError
|
|
||||||
sa.assemble([r], [r])
|
|
||||||
else:
|
|
||||||
raise NotImplementedError
|
|
||||||
|
|
||||||
def visit_assign_special(self, sa, node, statements):
|
|
||||||
value = node.value
|
|
||||||
assert(isinstance(value, ast.Call))
|
|
||||||
if isinstance(value.func, ast.Name):
|
|
||||||
callee = self.symdict[value.func.id]
|
|
||||||
else:
|
|
||||||
raise NotImplementedError
|
|
||||||
|
|
||||||
if callee == transel.Register:
|
|
||||||
if len(value.args) != 1:
|
|
||||||
raise TypeError("Register() takes exactly 1 argument")
|
|
||||||
bits_sign = eval_ast(value.args[0], self.symdict)
|
|
||||||
if isinstance(node.targets[0], ast.Name):
|
|
||||||
targetname = node.targets[0].id
|
|
||||||
else:
|
|
||||||
targetname = "unk"
|
|
||||||
reg = ImplRegister(targetname, bits_sign)
|
|
||||||
self.registers.append(reg)
|
|
||||||
for target in node.targets:
|
|
||||||
if isinstance(target, ast.Name):
|
|
||||||
self.symdict[target.id] = reg
|
|
||||||
else:
|
|
||||||
raise NotImplementedError
|
|
||||||
else:
|
|
||||||
return self.visit_io_pattern(sa, node.targets, callee, value.args, value.keywords, statements)
|
|
||||||
|
|
||||||
def visit_io_pattern(self, sa, targets, model, args, keywords, statements):
|
|
||||||
# first statement is <modelname> = <model>(<args>)
|
|
||||||
if len(targets) != 1 or not isinstance(targets[0], ast.Name):
|
|
||||||
raise NotImplementedError("Unrecognized I/O pattern")
|
|
||||||
modelname = targets[0].id
|
|
||||||
if modelname in self.symdict:
|
|
||||||
raise NotImplementedError("I/O model name is not free")
|
|
||||||
|
|
||||||
# second statement must be yield <modelname>
|
|
||||||
try:
|
|
||||||
ystatement = next(statements)
|
|
||||||
except StopIteration:
|
|
||||||
raise NotImplementedError("Incomplete or fragmented I/O pattern")
|
|
||||||
if not isinstance(ystatement, ast.Expr) \
|
|
||||||
or not isinstance(ystatement.value, ast.Yield) \
|
|
||||||
or not isinstance(ystatement.value.value, ast.Name) \
|
|
||||||
or ystatement.value.value.id != modelname:
|
|
||||||
print(ast.dump(ystatement))
|
|
||||||
raise NotImplementedError("Unrecognized I/O pattern")
|
|
||||||
|
|
||||||
# following optional statements are assignments to registers
|
|
||||||
# with <modelname> used in expressions.
|
|
||||||
from_model = []
|
|
||||||
while True:
|
|
||||||
try:
|
|
||||||
fstatement = next(statements)
|
|
||||||
except StopIteration:
|
|
||||||
fstatement = None
|
|
||||||
if not isinstance(fstatement, ast.Assign) \
|
|
||||||
or not _is_name_used(fstatement.value, modelname):
|
|
||||||
break
|
|
||||||
tregs = []
|
|
||||||
for target in fstatement.targets:
|
|
||||||
if isinstance(target, ast.Attribute) and target.attr == "store":
|
|
||||||
if isinstance(target.value, ast.Name):
|
|
||||||
tregs.append(self.symdict[target.value.id])
|
|
||||||
else:
|
|
||||||
raise NotImplementedError
|
|
||||||
else:
|
|
||||||
raise NotImplementedError
|
|
||||||
from_model.append((tregs, fstatement.value))
|
|
||||||
|
|
||||||
states, exit_states = gen_io(self, modelname, model, args, keywords, from_model)
|
|
||||||
sa.assemble(states, exit_states)
|
|
||||||
return fstatement
|
|
||||||
|
|
||||||
def visit_if(self, sa, node):
|
|
||||||
test = self.ec.visit_expr(node.test)
|
|
||||||
states_t, exit_states_t = self.visit_block(node.body)
|
|
||||||
states_f, exit_states_f = self.visit_block(node.orelse)
|
|
||||||
exit_states = exit_states_t + exit_states_f
|
|
||||||
|
|
||||||
test_state_stmt = If(test, id_next_state(states_t[0]))
|
|
||||||
test_state = [test_state_stmt]
|
|
||||||
if states_f:
|
|
||||||
test_state_stmt.Else(id_next_state(states_f[0]))
|
|
||||||
else:
|
|
||||||
exit_states.append(test_state)
|
|
||||||
|
|
||||||
sa.assemble([test_state] + states_t + states_f,
|
|
||||||
exit_states)
|
|
||||||
|
|
||||||
def visit_while(self, sa, node):
|
|
||||||
test = self.ec.visit_expr(node.test)
|
|
||||||
states_b, exit_states_b = self.visit_block(node.body)
|
|
||||||
|
|
||||||
test_state = [If(test, id_next_state(states_b[0]))]
|
|
||||||
for exit_state in exit_states_b:
|
|
||||||
exit_state.insert(0, id_next_state(test_state))
|
|
||||||
|
|
||||||
sa.assemble([test_state] + states_b, [test_state])
|
|
||||||
|
|
||||||
def visit_for(self, sa, node):
|
|
||||||
if not isinstance(node.target, ast.Name):
|
|
||||||
raise NotImplementedError
|
|
||||||
target = node.target.id
|
|
||||||
if target in self.symdict:
|
|
||||||
raise NotImplementedError("For loop target must use an available name")
|
|
||||||
it = self.visit_iterator(node.iter)
|
|
||||||
states = []
|
|
||||||
last_exit_states = []
|
|
||||||
for iteration in it:
|
|
||||||
self.symdict[target] = iteration
|
|
||||||
states_b, exit_states_b = self.visit_block(node.body)
|
|
||||||
for exit_state in last_exit_states:
|
|
||||||
exit_state.insert(0, id_next_state(states_b[0]))
|
|
||||||
last_exit_states = exit_states_b
|
|
||||||
states += states_b
|
|
||||||
del self.symdict[target]
|
|
||||||
sa.assemble(states, last_exit_states)
|
|
||||||
|
|
||||||
def visit_iterator(self, node):
|
|
||||||
return eval_ast(node, self.symdict)
|
|
||||||
|
|
||||||
def visit_expr_statement(self, sa, node):
|
|
||||||
if isinstance(node.value, ast.Yield):
|
|
||||||
yvalue = node.value.value
|
|
||||||
if not isinstance(yvalue, ast.Call) or not isinstance(yvalue.func, ast.Name):
|
|
||||||
raise NotImplementedError("Unrecognized I/O pattern")
|
|
||||||
callee = self.symdict[yvalue.func.id]
|
|
||||||
states, exit_states = gen_io(self, None, callee, yvalue.args, yvalue.keywords, [])
|
|
||||||
sa.assemble(states, exit_states)
|
|
||||||
else:
|
|
||||||
raise NotImplementedError
|
|
||||||
|
|
||||||
class Pytholite(UnifiedIOObject):
|
|
||||||
def __init__(self, func, *args, **kwargs):
|
|
||||||
self.func = func
|
|
||||||
self.args = args
|
|
||||||
self.kwargs = kwargs
|
|
||||||
|
|
||||||
def do_finalize(self):
|
|
||||||
UnifiedIOObject.do_finalize(self)
|
|
||||||
if self.get_dataflow():
|
|
||||||
self.busy.reset = 1
|
|
||||||
self.memory_ports = dict()
|
|
||||||
for key in xdir(self):
|
|
||||||
mem = getattr(self, key)
|
|
||||||
if isinstance(mem, Memory):
|
|
||||||
port = mem.get_port(write_capable=True, we_granularity=8)
|
|
||||||
self.specials += port
|
|
||||||
self.memory_ports[mem] = port
|
|
||||||
self._compile()
|
|
||||||
|
|
||||||
def _compile(self):
|
|
||||||
tree = ast.parse(inspect.getsource(self.func))
|
|
||||||
symdict = self.func.__globals__.copy()
|
|
||||||
registers = []
|
|
||||||
|
|
||||||
states = _Compiler(self, symdict, registers).visit_top(tree, self.args, self.kwargs)
|
|
||||||
|
|
||||||
for register in registers:
|
|
||||||
if register.source_encoding:
|
|
||||||
register.finalize()
|
|
||||||
self.submodules += register
|
|
||||||
|
|
||||||
fsm = implement_fsm(states)
|
|
||||||
self.submodules += TransformModule(LowerAbstractLoad().visit, fsm)
|
|
|
@ -1,122 +0,0 @@
|
||||||
import ast
|
|
||||||
|
|
||||||
from migen.fhdl.structure import *
|
|
||||||
from migen.fhdl.structure import _Slice
|
|
||||||
from migen.pytholite import transel
|
|
||||||
from migen.pytholite.reg import *
|
|
||||||
from migen.pytholite.util import eval_ast
|
|
||||||
|
|
||||||
class ExprCompiler:
|
|
||||||
def __init__(self, symdict):
|
|
||||||
self.symdict = symdict
|
|
||||||
|
|
||||||
def visit_expr(self, node):
|
|
||||||
# Attempt compile-time evaluation first
|
|
||||||
try:
|
|
||||||
result = eval_ast(node, self.symdict)
|
|
||||||
except:
|
|
||||||
result = None
|
|
||||||
if isinstance(result, int):
|
|
||||||
return result
|
|
||||||
|
|
||||||
if isinstance(node, ast.Call):
|
|
||||||
return self.visit_expr_call(node)
|
|
||||||
elif isinstance(node, ast.BinOp):
|
|
||||||
return self.visit_expr_binop(node)
|
|
||||||
elif isinstance(node, ast.Compare):
|
|
||||||
return self.visit_expr_compare(node)
|
|
||||||
elif isinstance(node, ast.Name):
|
|
||||||
return self.visit_expr_name(node)
|
|
||||||
elif isinstance(node, ast.Num):
|
|
||||||
return self.visit_expr_num(node)
|
|
||||||
elif isinstance(node, ast.Attribute):
|
|
||||||
return self.visit_expr_attribute(node)
|
|
||||||
elif isinstance(node, ast.Subscript):
|
|
||||||
return self.visit_expr_subscript(node)
|
|
||||||
else:
|
|
||||||
raise NotImplementedError
|
|
||||||
|
|
||||||
def visit_expr_call(self, node):
|
|
||||||
if isinstance(node.func, ast.Name):
|
|
||||||
callee = self.symdict[node.func.id]
|
|
||||||
else:
|
|
||||||
raise NotImplementedError
|
|
||||||
if callee == transel.bitslice:
|
|
||||||
if len(node.args) != 2 and len(node.args) != 3:
|
|
||||||
raise TypeError("bitslice() takes 2 or 3 arguments")
|
|
||||||
val = self.visit_expr(node.args[0])
|
|
||||||
low = eval_ast(node.args[1], self.symdict)
|
|
||||||
if len(node.args) == 3:
|
|
||||||
up = eval_ast(node.args[2], self.symdict)
|
|
||||||
else:
|
|
||||||
up = low + 1
|
|
||||||
return _Slice(val, low, up)
|
|
||||||
else:
|
|
||||||
raise NotImplementedError
|
|
||||||
|
|
||||||
def visit_expr_binop(self, node):
|
|
||||||
left = self.visit_expr(node.left)
|
|
||||||
right = self.visit_expr(node.right)
|
|
||||||
if isinstance(node.op, ast.Add):
|
|
||||||
return left + right
|
|
||||||
elif isinstance(node.op, ast.Sub):
|
|
||||||
return left - right
|
|
||||||
elif isinstance(node.op, ast.Mult):
|
|
||||||
return left * right
|
|
||||||
elif isinstance(node.op, ast.LShift):
|
|
||||||
return left << right
|
|
||||||
elif isinstance(node.op, ast.RShift):
|
|
||||||
return left >> right
|
|
||||||
elif isinstance(node.op, ast.BitOr):
|
|
||||||
return left | right
|
|
||||||
elif isinstance(node.op, ast.BitXor):
|
|
||||||
return left ^ right
|
|
||||||
elif isinstance(node.op, ast.BitAnd):
|
|
||||||
return left & right
|
|
||||||
else:
|
|
||||||
raise NotImplementedError
|
|
||||||
|
|
||||||
def visit_expr_compare(self, node):
|
|
||||||
test = self.visit_expr(node.left)
|
|
||||||
r = None
|
|
||||||
for op, rcomparator in zip(node.ops, node.comparators):
|
|
||||||
comparator = self.visit_expr(rcomparator)
|
|
||||||
if isinstance(op, ast.Eq):
|
|
||||||
comparison = test == comparator
|
|
||||||
elif isinstance(op, ast.NotEq):
|
|
||||||
comparison = test != comparator
|
|
||||||
elif isinstance(op, ast.Lt):
|
|
||||||
comparison = test < comparator
|
|
||||||
elif isinstance(op, ast.LtE):
|
|
||||||
comparison = test <= comparator
|
|
||||||
elif isinstance(op, ast.Gt):
|
|
||||||
comparison = test > comparator
|
|
||||||
elif isinstance(op, ast.GtE):
|
|
||||||
comparison = test >= comparator
|
|
||||||
else:
|
|
||||||
raise NotImplementedError
|
|
||||||
if r is None:
|
|
||||||
r = comparison
|
|
||||||
else:
|
|
||||||
r = r & comparison
|
|
||||||
test = comparator
|
|
||||||
return r
|
|
||||||
|
|
||||||
def visit_expr_name(self, node):
|
|
||||||
if node.id == "True":
|
|
||||||
return 1
|
|
||||||
if node.id == "False":
|
|
||||||
return 0
|
|
||||||
r = self.symdict[node.id]
|
|
||||||
if isinstance(r, ImplRegister):
|
|
||||||
r = r.storage
|
|
||||||
return r
|
|
||||||
|
|
||||||
def visit_expr_num(self, node):
|
|
||||||
return node.n
|
|
||||||
|
|
||||||
def visit_expr_attribute(self, node):
|
|
||||||
raise NotImplementedError
|
|
||||||
|
|
||||||
def visit_expr_subscript(self, node):
|
|
||||||
raise NotImplementedError
|
|
|
@ -1,201 +0,0 @@
|
||||||
import ast
|
|
||||||
from itertools import zip_longest
|
|
||||||
|
|
||||||
from migen.fhdl.std import *
|
|
||||||
from migen.flow.actor import Source, Sink
|
|
||||||
from migen.flow.transactions import *
|
|
||||||
from migen.bus import wishbone
|
|
||||||
from migen.bus.transactions import *
|
|
||||||
from migen.pytholite.util import *
|
|
||||||
from migen.pytholite.expr import ExprCompiler
|
|
||||||
|
|
||||||
class _TokenPullExprCompiler(ExprCompiler):
|
|
||||||
def __init__(self, symdict, modelname, ep):
|
|
||||||
ExprCompiler.__init__(self, symdict)
|
|
||||||
self.modelname = modelname
|
|
||||||
self.ep = ep
|
|
||||||
|
|
||||||
def visit_expr_subscript(self, node):
|
|
||||||
# check that we are subscripting <modelname>.value
|
|
||||||
if not isinstance(node.value, ast.Attribute) \
|
|
||||||
or node.value.attr != "value" \
|
|
||||||
or not isinstance(node.value.value, ast.Name) \
|
|
||||||
or node.value.value.id != self.modelname:
|
|
||||||
raise NotImplementedError
|
|
||||||
|
|
||||||
if not isinstance(node.slice, ast.Index):
|
|
||||||
raise NotImplementedError
|
|
||||||
field = eval_ast(node.slice.value, self.symdict)
|
|
||||||
signal = getattr(self.ep.payload, field)
|
|
||||||
|
|
||||||
return signal
|
|
||||||
|
|
||||||
def _gen_df_io(compiler, modelname, to_model, from_model):
|
|
||||||
epname = eval_ast(to_model["endpoint"], compiler.symdict)
|
|
||||||
values = to_model["value"]
|
|
||||||
idle_wait = eval_ast(to_model["idle_wait"], compiler.symdict)
|
|
||||||
ep = getattr(compiler.ioo, epname)
|
|
||||||
if idle_wait:
|
|
||||||
state = [compiler.ioo.busy.eq(0)]
|
|
||||||
else:
|
|
||||||
state = []
|
|
||||||
|
|
||||||
if isinstance(values, ast.Name) and values.id == "None":
|
|
||||||
# token pull from sink
|
|
||||||
if not isinstance(ep, Sink):
|
|
||||||
raise TypeError("Attempted to pull from source")
|
|
||||||
ec = _TokenPullExprCompiler(compiler.symdict, modelname, ep)
|
|
||||||
for target_regs, expr in from_model:
|
|
||||||
cexpr = ec.visit_expr(expr)
|
|
||||||
state += [reg.load(cexpr) for reg in target_regs]
|
|
||||||
state += [
|
|
||||||
ep.ack.eq(1),
|
|
||||||
If(~ep.stb, id_next_state(state))
|
|
||||||
]
|
|
||||||
return [state], [state]
|
|
||||||
else:
|
|
||||||
# token push to source
|
|
||||||
if not isinstance(ep, Source):
|
|
||||||
raise TypeError("Attempted to push to sink")
|
|
||||||
if from_model:
|
|
||||||
raise TypeError("Attempted to read from pushed token")
|
|
||||||
if not isinstance(values, ast.Dict):
|
|
||||||
raise NotImplementedError
|
|
||||||
for akey, value in zip(values.keys, values.values):
|
|
||||||
key = eval_ast(akey, compiler.symdict)
|
|
||||||
signal = getattr(ep.payload, key)
|
|
||||||
state.append(signal.eq(compiler.ec.visit_expr(value)))
|
|
||||||
state += [
|
|
||||||
ep.stb.eq(1),
|
|
||||||
If(~ep.ack, id_next_state(state))
|
|
||||||
]
|
|
||||||
return [state], [state]
|
|
||||||
|
|
||||||
class _BusReadExprCompiler(ExprCompiler):
|
|
||||||
def __init__(self, symdict, modelname, data_signal):
|
|
||||||
ExprCompiler.__init__(self, symdict)
|
|
||||||
self.modelname = modelname
|
|
||||||
self.data_signal = data_signal
|
|
||||||
|
|
||||||
def visit_expr_attribute(self, node):
|
|
||||||
# recognize <modelname>.data as the bus read signal, raise exception otherwise
|
|
||||||
if not isinstance(node.value, ast.Name) \
|
|
||||||
or node.value.id != self.modelname \
|
|
||||||
or node.attr != "data":
|
|
||||||
raise NotImplementedError
|
|
||||||
return self.data_signal
|
|
||||||
|
|
||||||
def _gen_wishbone_io(compiler, modelname, model, to_model, from_model, bus):
|
|
||||||
state = [
|
|
||||||
bus.cyc.eq(1),
|
|
||||||
bus.stb.eq(1),
|
|
||||||
bus.adr.eq(compiler.ec.visit_expr(to_model["address"])),
|
|
||||||
]
|
|
||||||
|
|
||||||
if model == TWrite:
|
|
||||||
if from_model:
|
|
||||||
raise TypeError("Attempted to read from write transaction")
|
|
||||||
state += [
|
|
||||||
bus.we.eq(1),
|
|
||||||
bus.dat_w.eq(compiler.ec.visit_expr(to_model["data"]))
|
|
||||||
]
|
|
||||||
sel = to_model["sel"]
|
|
||||||
if isinstance(sel, ast.Name) and sel.id == "None":
|
|
||||||
nbytes = (flen(bus.dat_w) + 7)//8
|
|
||||||
state.append(bus.sel.eq(2**nbytes-1))
|
|
||||||
else:
|
|
||||||
state.append(bus.sel.eq(compiler.ec.visit_expr(sel)))
|
|
||||||
else:
|
|
||||||
ec = _BusReadExprCompiler(compiler.symdict, modelname, bus.dat_r)
|
|
||||||
for target_regs, expr in from_model:
|
|
||||||
cexpr = ec.visit_expr(expr)
|
|
||||||
state += [reg.load(cexpr) for reg in target_regs]
|
|
||||||
state.append(If(~bus.ack, id_next_state(state)))
|
|
||||||
return [state], [state]
|
|
||||||
|
|
||||||
def _gen_memory_io(compiler, modelname, model, to_model, from_model, port):
|
|
||||||
s1 = [port.adr.eq(compiler.ec.visit_expr(to_model["address"]))]
|
|
||||||
if model == TWrite:
|
|
||||||
if from_model:
|
|
||||||
raise TypeError("Attempted to read from write transaction")
|
|
||||||
s1.append(port.dat_w.eq(compiler.ec.visit_expr(to_model["data"])))
|
|
||||||
sel = to_model["sel"]
|
|
||||||
if isinstance(sel, ast.Name) and sel.id == "None":
|
|
||||||
nbytes = (flen(port.dat_w) + 7)//8
|
|
||||||
s1.append(port.we.eq(2**nbytes-1))
|
|
||||||
else:
|
|
||||||
s1.append(port.we.eq(compiler.ec.visit_expr(sel)))
|
|
||||||
return [s1], [s1]
|
|
||||||
else:
|
|
||||||
s2 = []
|
|
||||||
s1.append(id_next_state(s2))
|
|
||||||
ec = _BusReadExprCompiler(compiler.symdict, modelname, port.dat_r)
|
|
||||||
for target_regs, expr in from_model:
|
|
||||||
cexpr = ec.visit_expr(expr)
|
|
||||||
s2 += [reg.load(cexpr) for reg in target_regs]
|
|
||||||
return [s1, s2], [s2]
|
|
||||||
|
|
||||||
def _gen_bus_io(compiler, modelname, model, to_model, from_model):
|
|
||||||
busname = eval_ast(to_model["busname"], compiler.symdict)
|
|
||||||
if busname is None:
|
|
||||||
buses = compiler.ioo.get_buses()
|
|
||||||
if len(buses) != 1:
|
|
||||||
raise TypeError("Bus name not specified")
|
|
||||||
bus = list(buses.values())[0]
|
|
||||||
else:
|
|
||||||
bus = getattr(compiler.ioo, busname)
|
|
||||||
if isinstance(bus, wishbone.Interface):
|
|
||||||
return _gen_wishbone_io(compiler, modelname, model, to_model, from_model, bus)
|
|
||||||
elif isinstance(bus, Memory):
|
|
||||||
port = compiler.ioo.memory_ports[bus]
|
|
||||||
return _gen_memory_io(compiler, modelname, model, to_model, from_model, port)
|
|
||||||
else:
|
|
||||||
raise NotImplementedError("Unsupported bus")
|
|
||||||
|
|
||||||
def _decode_args(desc, args, args_kw):
|
|
||||||
d = {}
|
|
||||||
argnames = set()
|
|
||||||
for param, value in zip_longest(desc, args):
|
|
||||||
if param is None:
|
|
||||||
raise TypeError("Too many arguments")
|
|
||||||
if isinstance(param, tuple):
|
|
||||||
name, default = param
|
|
||||||
else:
|
|
||||||
name, default = param, None
|
|
||||||
|
|
||||||
# build the set of argument names at the same time
|
|
||||||
argnames.add(name)
|
|
||||||
|
|
||||||
if value is None:
|
|
||||||
if default is None:
|
|
||||||
raise TypeError("No default value for parameter " + name)
|
|
||||||
else:
|
|
||||||
d[name] = default
|
|
||||||
else:
|
|
||||||
d[name] = value
|
|
||||||
for akw in args_kw:
|
|
||||||
if akw.arg not in argnames:
|
|
||||||
raise TypeError("Parameter " + akw.arg + " does not exist")
|
|
||||||
d[akw.arg] = akw.value
|
|
||||||
return d
|
|
||||||
|
|
||||||
def gen_io(compiler, modelname, model, to_model, to_model_kw, from_model):
|
|
||||||
if model == Token:
|
|
||||||
desc = [
|
|
||||||
"endpoint",
|
|
||||||
("value", ast.Name("None", ast.Load(), lineno=0, col_offset=0)),
|
|
||||||
("idle_wait", ast.Name("False", ast.Load(), lineno=0, col_offset=0))
|
|
||||||
]
|
|
||||||
args = _decode_args(desc, to_model, to_model_kw)
|
|
||||||
return _gen_df_io(compiler, modelname, args, from_model)
|
|
||||||
elif model == TRead or model == TWrite:
|
|
||||||
desc = [
|
|
||||||
"address",
|
|
||||||
("data", ast.Num(0)),
|
|
||||||
("sel", ast.Name("None", ast.Load(), lineno=0, col_offset=0)),
|
|
||||||
("busname", ast.Name("None", ast.Load(), lineno=0, col_offset=0))
|
|
||||||
]
|
|
||||||
args = _decode_args(desc, to_model, to_model_kw)
|
|
||||||
return _gen_bus_io(compiler, modelname, model, args, from_model)
|
|
||||||
else:
|
|
||||||
raise NotImplementedError
|
|
|
@ -1,41 +0,0 @@
|
||||||
from operator import itemgetter
|
|
||||||
|
|
||||||
from migen.fhdl.std import *
|
|
||||||
from migen.fhdl import visit as fhdl
|
|
||||||
|
|
||||||
class AbstractLoad:
|
|
||||||
def __init__(self, target, source):
|
|
||||||
self.target = target
|
|
||||||
self.source = source
|
|
||||||
|
|
||||||
def lower(self):
|
|
||||||
if not self.target.finalized:
|
|
||||||
raise FinalizeError
|
|
||||||
return self.target.sel.eq(self.target.source_encoding[id(self.source)])
|
|
||||||
|
|
||||||
class LowerAbstractLoad(fhdl.NodeTransformer):
|
|
||||||
def visit_unknown(self, node):
|
|
||||||
if isinstance(node, AbstractLoad):
|
|
||||||
return node.lower()
|
|
||||||
else:
|
|
||||||
return node
|
|
||||||
|
|
||||||
class ImplRegister(Module):
|
|
||||||
def __init__(self, name, bits_sign):
|
|
||||||
self.name = name
|
|
||||||
self.storage = Signal(bits_sign, name=self.name)
|
|
||||||
self.source_encoding = {}
|
|
||||||
self.id_to_source = {}
|
|
||||||
|
|
||||||
def load(self, source):
|
|
||||||
if id(source) not in self.source_encoding:
|
|
||||||
self.source_encoding[id(source)] = len(self.source_encoding) + 1
|
|
||||||
self.id_to_source[id(source)] = source
|
|
||||||
return AbstractLoad(self, source)
|
|
||||||
|
|
||||||
def do_finalize(self):
|
|
||||||
self.sel = Signal(max=len(self.source_encoding)+1, name="pl_regsel_"+self.name)
|
|
||||||
# do nothing when sel == 0
|
|
||||||
items = sorted(self.source_encoding.items(), key=itemgetter(1))
|
|
||||||
cases = dict((v, self.storage.eq(self.id_to_source[k])) for k, v in items)
|
|
||||||
self.sync += Case(self.sel, cases)
|
|
|
@ -1,198 +0,0 @@
|
||||||
import operator
|
|
||||||
|
|
||||||
def bitslice(val, low, up=None):
|
|
||||||
if up is None:
|
|
||||||
up = low + 1
|
|
||||||
nbits = up - low
|
|
||||||
mask = (2**nbits - 1) << low
|
|
||||||
return (val & mask) >> low
|
|
||||||
|
|
||||||
class Register:
|
|
||||||
def __init__(self, bits_sign):
|
|
||||||
if isinstance(bits_sign, tuple):
|
|
||||||
self._nbits, self._signed = bits_sign
|
|
||||||
else:
|
|
||||||
self._nbits, self._signed = bits_sign, False
|
|
||||||
self._val = 0
|
|
||||||
|
|
||||||
def _set_store(self, val):
|
|
||||||
if self._signed:
|
|
||||||
sbw = 2**(self._nbits - 1)
|
|
||||||
self._val = val & (sbw - 1)
|
|
||||||
if val & sbw:
|
|
||||||
self._val -= sbw
|
|
||||||
else:
|
|
||||||
self._val = val & (2**self._nbits - 1)
|
|
||||||
store = property(None, _set_store)
|
|
||||||
|
|
||||||
def __nonzero__(self):
|
|
||||||
if self._val:
|
|
||||||
return 1
|
|
||||||
else:
|
|
||||||
return 0
|
|
||||||
|
|
||||||
def __len__(self):
|
|
||||||
return self._nbits
|
|
||||||
|
|
||||||
def __add__(self, other):
|
|
||||||
if isinstance(other, Register):
|
|
||||||
return self._val + other._val
|
|
||||||
else:
|
|
||||||
return self._val + other
|
|
||||||
def __radd__(self, other):
|
|
||||||
return other + self._val
|
|
||||||
|
|
||||||
def __sub__(self, other):
|
|
||||||
if isinstance(other, Register):
|
|
||||||
return self._val - other._val
|
|
||||||
else:
|
|
||||||
return self._val - other
|
|
||||||
def __rsub__(self, other):
|
|
||||||
return other - self._val
|
|
||||||
|
|
||||||
def __mul__(self, other):
|
|
||||||
if isinstance(other, Register):
|
|
||||||
return self._val * other._val
|
|
||||||
else:
|
|
||||||
return self._val * other
|
|
||||||
def __rmul__(self, other):
|
|
||||||
return other * self._val
|
|
||||||
|
|
||||||
def __div__(self, other):
|
|
||||||
if isinstance(other, Register):
|
|
||||||
return self._val / other._val
|
|
||||||
else:
|
|
||||||
return self._val / other
|
|
||||||
def __rdiv__(self, other):
|
|
||||||
return other / self._val
|
|
||||||
|
|
||||||
def __truediv__(self, other):
|
|
||||||
if isinstance(other, Register):
|
|
||||||
return operator.truediv(self._val, other._val)
|
|
||||||
else:
|
|
||||||
return operator.truediv(self._val, other)
|
|
||||||
def __rtruediv__(self, other):
|
|
||||||
return operator.truediv(other, self._val)
|
|
||||||
|
|
||||||
def __floordiv__(self, other):
|
|
||||||
if isinstance(other, Register):
|
|
||||||
return self._val // other._val
|
|
||||||
else:
|
|
||||||
return self._val // other
|
|
||||||
def __rfloordiv__(self, other):
|
|
||||||
return other // self._val
|
|
||||||
|
|
||||||
def __mod__(self, other):
|
|
||||||
if isinstance(other, Register):
|
|
||||||
return self._val % other._val
|
|
||||||
else:
|
|
||||||
return self._val % other
|
|
||||||
def __rmod__(self, other):
|
|
||||||
return other % self._val
|
|
||||||
|
|
||||||
def __pow__(self, other):
|
|
||||||
if isinstance(other, Register):
|
|
||||||
return self._val ** other._val
|
|
||||||
else:
|
|
||||||
return self._val ** other
|
|
||||||
def __rpow__(self, other):
|
|
||||||
return other ** self._val
|
|
||||||
|
|
||||||
def __lshift__(self, other):
|
|
||||||
if isinstance(other, Register):
|
|
||||||
return self._val << other._val
|
|
||||||
else:
|
|
||||||
return self._val << other
|
|
||||||
def __rlshift__(self, other):
|
|
||||||
return other << self._val
|
|
||||||
|
|
||||||
def __rshift__(self, other):
|
|
||||||
if isinstance(other, Register):
|
|
||||||
return self._val >> other._val
|
|
||||||
else:
|
|
||||||
return self._val >> other
|
|
||||||
def __rrshift__(self, other):
|
|
||||||
return other >> self._val
|
|
||||||
|
|
||||||
def __and__(self, other):
|
|
||||||
if isinstance(other, Register):
|
|
||||||
return self._val & other._val
|
|
||||||
else:
|
|
||||||
return self._val & other
|
|
||||||
def __rand__(self, other):
|
|
||||||
return other & self._val
|
|
||||||
|
|
||||||
def __or__(self, other):
|
|
||||||
if isinstance(other, Register):
|
|
||||||
return self._val | other._val
|
|
||||||
else:
|
|
||||||
return self._val | other
|
|
||||||
def __ror__(self, other):
|
|
||||||
return other | self._val
|
|
||||||
|
|
||||||
def __xor__(self, other):
|
|
||||||
if isinstance(other, Register):
|
|
||||||
return self._val ^ other._val
|
|
||||||
else:
|
|
||||||
return self._val ^ other
|
|
||||||
def __rxor__(self, other):
|
|
||||||
return other ^ self._val
|
|
||||||
|
|
||||||
def __neg__(self):
|
|
||||||
return -self._val
|
|
||||||
|
|
||||||
def __pos__(self):
|
|
||||||
return +self._val
|
|
||||||
|
|
||||||
def __abs__(self):
|
|
||||||
return abs(self._val)
|
|
||||||
|
|
||||||
def __invert__(self):
|
|
||||||
return ~self._val
|
|
||||||
|
|
||||||
def __int__(self):
|
|
||||||
return int(self._val)
|
|
||||||
|
|
||||||
def __float__(self):
|
|
||||||
return float(self._val)
|
|
||||||
|
|
||||||
def __oct__(self):
|
|
||||||
return oct(self._val)
|
|
||||||
|
|
||||||
def __hex__(self):
|
|
||||||
return hex(self._val)
|
|
||||||
|
|
||||||
def __index__(self):
|
|
||||||
return int(self._val)
|
|
||||||
|
|
||||||
def __lt__(self, other):
|
|
||||||
return self._val < other
|
|
||||||
|
|
||||||
def __le__(self, other):
|
|
||||||
return self._val <= other
|
|
||||||
|
|
||||||
def __eq__(self, other):
|
|
||||||
return self._val == other
|
|
||||||
|
|
||||||
def __ge__(self, other):
|
|
||||||
return self._val >= other
|
|
||||||
|
|
||||||
def __gt__(self, other):
|
|
||||||
return self._val > other
|
|
||||||
|
|
||||||
def __ne__(self, other):
|
|
||||||
return self._val != other
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return str(self._val)
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return "Register(" + repr(self._val) + ")"
|
|
||||||
|
|
||||||
def _augm(self, other):
|
|
||||||
raise TypeError("Register objects do not support augmented assignment")
|
|
||||||
__iadd__ = __isub__ = __idiv__ = __imul__ = __ipow__ = __imod__ = _augm
|
|
||||||
__ior__ = __iand__ = __ixor__ = __irshift__ = __ilshift__ = _augm
|
|
||||||
|
|
||||||
def __setitem__(self, key, val):
|
|
||||||
raise TypeError("Register objects do not support item/slice assignment")
|
|
|
@ -1,33 +0,0 @@
|
||||||
import ast
|
|
||||||
|
|
||||||
from migen.genlib.fsm import FSM, NextState
|
|
||||||
|
|
||||||
def id_next_state(l):
|
|
||||||
return NextState(id(l))
|
|
||||||
|
|
||||||
# entry state is first state returned
|
|
||||||
class StateAssembler:
|
|
||||||
def __init__(self):
|
|
||||||
self.states = []
|
|
||||||
self.exit_states = []
|
|
||||||
|
|
||||||
def assemble(self, n_states, n_exit_states):
|
|
||||||
self.states += n_states
|
|
||||||
for exit_state in self.exit_states:
|
|
||||||
exit_state.insert(0, id_next_state(n_states[0]))
|
|
||||||
self.exit_states = n_exit_states
|
|
||||||
|
|
||||||
def ret(self):
|
|
||||||
return self.states, self.exit_states
|
|
||||||
|
|
||||||
def implement_fsm(states):
|
|
||||||
fsm = FSM()
|
|
||||||
for state in states:
|
|
||||||
fsm.act(id(state), state)
|
|
||||||
return fsm
|
|
||||||
|
|
||||||
def eval_ast(expr, symdict):
|
|
||||||
if not isinstance(expr, ast.Expression):
|
|
||||||
expr = ast.Expression(expr)
|
|
||||||
code = compile(expr, "<ast>", "eval")
|
|
||||||
return eval(code, symdict)
|
|
Loading…
Reference in a new issue