pytholite/io: support Wishbone writes

This commit is contained in:
Sebastien Bourdeauducq 2012-11-23 12:41:50 +01:00
parent f098c5c695
commit 0b24a2ff36
1 changed files with 82 additions and 12 deletions

View File

@ -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 @@ class _TokenPullExprCompiler(ExprCompiler):
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,79 @@ def gen_df_io(compiler, modelname, to_model, from_model):
]
return [state], [state]
def gen_io(compiler, modelname, model, to_model, from_model):
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))
# TODO
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