Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Comparing changes

Choose two branches to see what's changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
  • 5 commits
  • 4 files changed
  • 0 commit comments
  • 1 contributor
View
17 examples/pytholite/uio.py
@@ -13,8 +13,9 @@
def gen():
ds = Register(32)
- for i in range(10):
- r = TRead(i)
+ for i in range(5):
+ # NB: busname is optional when only one bus is configured
+ r = TRead(i, busname="wb")
yield r
ds.store = r.data
yield Token("result", {"r": ds})
@@ -55,11 +56,13 @@ def main():
buses={"wb": wishbone.Interface()})
run_sim(ng_native)
- #print("Simulating Pytholite:")
- #ng_pytholite = make_pytholite(gen, dataflow=[("result", Source, layout)])
- #run_sim(ng_pytholite)
+ print("Simulating Pytholite:")
+ ng_pytholite = make_pytholite(gen,
+ dataflow=[("result", Source, layout)],
+ buses={"wb": wishbone.Interface()})
+ run_sim(ng_pytholite)
- #print("Converting Pytholite to Verilog:")
- #print(verilog.convert(ng_pytholite.get_fragment()))
+ print("Converting Pytholite to Verilog:")
+ print(verilog.convert(ng_pytholite.get_fragment()))
main()
View
25 migen/fhdl/verilog.py
@@ -81,17 +81,20 @@ def _printnode(ns, at, level, node):
r += "\t"*level + "end\n"
return r
elif isinstance(node, Case):
- r = "\t"*level + "case (" + _printexpr(ns, node.test) + ")\n"
- for case in node.cases:
- r += "\t"*(level + 1) + _printexpr(ns, case[0]) + ": begin\n"
- r += _printnode(ns, at, level + 2, case[1])
- r += "\t"*(level + 1) + "end\n"
- if node.default:
- r += "\t"*(level + 1) + "default: begin\n"
- r += _printnode(ns, at, level + 2, node.default)
- r += "\t"*(level + 1) + "end\n"
- r += "\t"*level + "endcase\n"
- return r
+ if node.cases or node.default:
+ r = "\t"*level + "case (" + _printexpr(ns, node.test) + ")\n"
+ for case in node.cases:
+ r += "\t"*(level + 1) + _printexpr(ns, case[0]) + ": begin\n"
+ r += _printnode(ns, at, level + 2, case[1])
+ r += "\t"*(level + 1) + "end\n"
+ if node.default:
+ r += "\t"*(level + 1) + "default: begin\n"
+ r += _printnode(ns, at, level + 2, node.default)
+ r += "\t"*(level + 1) + "end\n"
+ r += "\t"*level + "endcase\n"
+ return r
+ else:
+ return ""
else:
raise TypeError
View
8 migen/pytholite/compiler.py
@@ -110,9 +110,9 @@ def visit_assign_special(self, sa, node, statements):
else:
raise NotImplementedError
else:
- return self.visit_io_pattern(sa, node.targets, callee, value.args, statements)
+ return self.visit_io_pattern(sa, node.targets, callee, value.args, value.keywords, statements)
- def visit_io_pattern(self, sa, targets, model, args, 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")
@@ -154,7 +154,7 @@ def visit_io_pattern(self, sa, targets, model, args, statements):
raise NotImplementedError
from_model.append((tregs, fstatement.value))
- states, exit_states = gen_io(self, modelname, model, args, from_model)
+ states, exit_states = gen_io(self, modelname, model, args, keywords, from_model)
sa.assemble(states, exit_states)
return fstatement
@@ -222,7 +222,7 @@ def visit_expr_statement(self, sa, node):
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, [])
+ states, exit_states = gen_io(self, None, callee, yvalue.args, yvalue.keywords, [])
sa.assemble(states, exit_states)
else:
raise NotImplementedError
View
111 migen/pytholite/io.py
@@ -1,8 +1,10 @@
import ast
+from itertools import zip_longest
from migen.fhdl.structure import *
from migen.uio.ioo import UnifiedIOObject
from migen.actorlib.sim import *
+from migen.bus import wishbone
from migen.bus.transactions import *
from migen.pytholite.fsm import *
from migen.pytholite.expr import ExprCompiler
@@ -32,14 +34,12 @@ def visit_expr_subscript(self, node):
return signal
-def gen_df_io(compiler, modelname, to_model, from_model):
- if len(to_model) == 1 or len(to_model) == 2:
- epname = ast.literal_eval(to_model[0])
- ep = compiler.ioo.endpoints[epname]
- else:
- raise TypeError("Token() takes 1 or 2 arguments")
+def _gen_df_io(compiler, modelname, to_model, from_model):
+ epname = ast.literal_eval(to_model["endpoint"])
+ values = to_model["value"]
+ ep = compiler.ioo.endpoints[epname]
- if len(to_model) == 1:
+ 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")
@@ -59,11 +59,10 @@ def gen_df_io(compiler, modelname, to_model, from_model):
raise TypeError("Attempted to push to sink")
if from_model:
raise TypeError("Attempted to read from pushed token")
- d = to_model[1]
- if not isinstance(d, ast.Dict):
+ if not isinstance(values, ast.Dict):
raise NotImplementedError
state = []
- for akey, value in zip(d.keys, d.values):
+ for akey, value in zip(values.keys, values.values):
key = ast.literal_eval(akey)
signal = getattr(ep.token, key)
state.append(signal.eq(compiler.ec.visit_expr(value)))
@@ -73,8 +72,96 @@ def gen_df_io(compiler, modelname, to_model, from_model):
]
return [state], [state]
-def gen_io(compiler, modelname, model, to_model, from_model):
+class _BusReadExprCompiler(ExprCompiler):
+ def __init__(self, symdict, modelname, data_signal):
+ super().__init__(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:
+ state.append(bus.we.eq(1))
+ if from_model:
+ raise TypeError("Attempted to read from write transaction")
+ else:
+ state.append(bus.we.eq(0))
+ 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, AbstractNextState(state)))
+ return [state], [state]
+
+def _gen_bus_io(compiler, modelname, model, to_model, from_model):
+ busname = ast.literal_eval(to_model["busname"])
+ if busname is None:
+ if len(compiler.ioo.buses) != 1:
+ raise TypeError("Bus name not specified")
+ bus = list(compiler.ioo.buses.values())[0]
+ else:
+ bus = compiler.ioo.buses[busname]
+ if isinstance(bus, wishbone.Interface):
+ return _gen_wishbone_io(compiler, modelname, model, to_model, from_model, bus)
+ 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:
- return gen_df_io(compiler, modelname, to_model, from_model)
+ desc = [
+ "endpoint",
+ ("value", ast.Name("None", ast.Load())),
+ ]
+ 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())),
+ ("busname", ast.Name("None", ast.Load()))
+ ]
+ args = _decode_args(desc, to_model, to_model_kw)
+ return _gen_bus_io(compiler, modelname, model, args, from_model)
else:
raise NotImplementedError

No commit comments for this range

Something went wrong with that request. Please try again.