+++ /dev/null
-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()
+++ /dev/null
-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()
+++ /dev/null
-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
+++ /dev/null
-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)
+++ /dev/null
-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
+++ /dev/null
-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
+++ /dev/null
-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)
+++ /dev/null
-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")
+++ /dev/null
-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)