From: Sebastien Bourdeauducq Date: Sat, 14 Mar 2015 21:48:03 +0000 (+0100) Subject: move pytholite to separate repos X-Git-Tag: 24jan2021_ls180~2099^2~186 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=beeaefcceac9fc3b1fdc1c5f40294ede9b72c8ca;p=litex.git move pytholite to separate repos --- diff --git a/examples/pytholite/basic.py b/examples/pytholite/basic.py deleted file mode 100644 index b93969ea..00000000 --- a/examples/pytholite/basic.py +++ /dev/null @@ -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() diff --git a/examples/pytholite/uio.py b/examples/pytholite/uio.py deleted file mode 100644 index 3002258d..00000000 --- a/examples/pytholite/uio.py +++ /dev/null @@ -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() diff --git a/migen/genlib/ioo.py b/migen/genlib/ioo.py deleted file mode 100644 index c41490f2..00000000 --- a/migen/genlib/ioo.py +++ /dev/null @@ -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 diff --git a/migen/pytholite/__init__.py b/migen/pytholite/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/migen/pytholite/compiler.py b/migen/pytholite/compiler.py deleted file mode 100644 index 6315cc41..00000000 --- a/migen/pytholite/compiler.py +++ /dev/null @@ -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 = () - 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 - 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 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) diff --git a/migen/pytholite/expr.py b/migen/pytholite/expr.py deleted file mode 100644 index b42de27c..00000000 --- a/migen/pytholite/expr.py +++ /dev/null @@ -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 diff --git a/migen/pytholite/io.py b/migen/pytholite/io.py deleted file mode 100644 index 57e11e12..00000000 --- a/migen/pytholite/io.py +++ /dev/null @@ -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 .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 .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 diff --git a/migen/pytholite/reg.py b/migen/pytholite/reg.py deleted file mode 100644 index e94a3be6..00000000 --- a/migen/pytholite/reg.py +++ /dev/null @@ -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) diff --git a/migen/pytholite/transel.py b/migen/pytholite/transel.py deleted file mode 100644 index 8a79768f..00000000 --- a/migen/pytholite/transel.py +++ /dev/null @@ -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") diff --git a/migen/pytholite/util.py b/migen/pytholite/util.py deleted file mode 100644 index 5b397169..00000000 --- a/migen/pytholite/util.py +++ /dev/null @@ -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, "", "eval") - return eval(code, symdict)