New 'specials' API

This commit is contained in:
Sebastien Bourdeauducq 2013-02-22 17:56:35 +01:00
parent e82ea19cdc
commit 49cfba50fa
18 changed files with 406 additions and 412 deletions

View file

@ -1,50 +1,60 @@
from migen.fhdl.structure import * from migen.fhdl.structure import *
from migen.fhdl.specials import Instance
from migen.bus import wishbone
from migen.fhdl import verilog from migen.fhdl import verilog
class LM32: class LM32:
def __init__(self): def __init__(self):
self.inst = Instance("lm32_top", self.ibus = i = wishbone.Interface()
self.dbus = d = wishbone.Interface()
self.interrupt = Signal(32)
self.ext_break = Signal()
self._i_adr_o = Signal(32)
self._d_adr_o = Signal(32)
self._inst = Instance("lm32_top",
Instance.ClockPort("clk_i"), Instance.ClockPort("clk_i"),
Instance.ResetPort("rst_i"), Instance.ResetPort("rst_i"),
Instance.Input("interrupt", 32),
Instance.Input("ext_break", 1),
Instance.Output("I_ADR_O", 32),
Instance.Output("I_DAT_O", 32),
Instance.Output("I_SEL_O", 4),
Instance.Output("I_CYC_O", 1),
Instance.Output("I_STB_O", 1),
Instance.Output("I_WE_O", 1),
Instance.Output("I_CTI_O", 3),
Instance.Output("I_LOCK_O", 1),
Instance.Output("I_BTE_O", 1),
Instance.Input("I_DAT_I", 32),
Instance.Input("I_ACK_I", 1),
Instance.Input("I_ERR_I", 1),
Instance.Input("I_RTY_I", 1),
Instance.Output("D_ADR_O", 32), Instance.Input("interrupt", self.interrupt),
Instance.Output("D_DAT_O", 32), #Instance.Input("ext_break", self.ext_break),
Instance.Output("D_SEL_O", 4),
Instance.Output("D_CYC_O", 1), Instance.Output("I_ADR_O", self._i_adr_o),
Instance.Output("D_STB_O", 1), Instance.Output("I_DAT_O", i.dat_w),
Instance.Output("D_WE_O", 1), Instance.Output("I_SEL_O", i.sel),
Instance.Output("D_CTI_O", 3), Instance.Output("I_CYC_O", i.cyc),
Instance.Output("D_LOCK_O", 1), Instance.Output("I_STB_O", i.stb),
Instance.Output("D_BTE_O", 1), Instance.Output("I_WE_O", i.we),
Instance.Input("D_DAT_I", 32), Instance.Output("I_CTI_O", i.cti),
Instance.Input("D_ACK_I", 1), Instance.Output("I_LOCK_O"),
Instance.Input("D_ERR_I", 1), Instance.Output("I_BTE_O", i.bte),
Instance.Input("D_RTY_I", 1), Instance.Input("I_DAT_I", i.dat_r),
Instance.Input("I_ACK_I", i.ack),
Instance.Input("I_ERR_I", i.err),
Instance.Input("I_RTY_I", 0),
name="lm32") Instance.Output("D_ADR_O", self._d_adr_o),
Instance.Output("D_DAT_O", d.dat_w),
Instance.Output("D_SEL_O", d.sel),
Instance.Output("D_CYC_O", d.cyc),
Instance.Output("D_STB_O", d.stb),
Instance.Output("D_WE_O", d.we),
Instance.Output("D_CTI_O", d.cti),
Instance.Output("D_LOCK_O"),
Instance.Output("D_BTE_O", d.bte),
Instance.Input("D_DAT_I", d.dat_r),
Instance.Input("D_ACK_I", d.ack),
Instance.Input("D_ERR_I", d.err),
Instance.Input("D_RTY_I", 0))
def get_fragment(self): def get_fragment(self):
return Fragment(instances=[self.inst]) comb = [
self.ibus.adr.eq(self._i_adr_o[2:]),
self.dbus.adr.eq(self._d_adr_o[2:])
]
return Fragment(comb=comb, specials={self._inst})
cpus = [LM32() for i in range(4)] cpus = [LM32() for i in range(4)]
frag = Fragment() frag = Fragment()
for cpu in cpus: for cpu in cpus:
frag += cpu.get_fragment() frag += cpu.get_fragment()
print(verilog.convert(frag, set([cpus[0].inst.get_io("interrupt"), cpus[0].inst.get_io("I_WE_O")]))) print(verilog.convert(frag, {cpus[0].interrupt}))

View file

@ -1,11 +1,12 @@
from migen.fhdl.structure import * from migen.fhdl.structure import Fragment
from migen.fhdl.specials import Memory
from migen.fhdl import verilog from migen.fhdl import verilog
mem = Memory(32, 100, init=[5, 18, 32]) mem = Memory(32, 100, init=[5, 18, 32])
p1 = mem.get_port(write_capable=True, we_granularity=8) p1 = mem.get_port(write_capable=True, we_granularity=8)
p2 = mem.get_port(has_re=True, clock_domain="rd") p2 = mem.get_port(has_re=True, clock_domain="rd")
f = Fragment(memories=[mem]) f = Fragment(specials={mem})
v = verilog.convert(f, ios={p1.adr, p1.dat_r, p1.we, p1.dat_w, v = verilog.convert(f, ios={p1.adr, p1.dat_r, p1.we, p1.dat_w,
p2.adr, p2.dat_r, p2.re}) p2.adr, p2.dat_r, p2.re})
print(v) print(v)

View file

@ -1,4 +1,5 @@
from migen.fhdl.structure import * from migen.fhdl.structure import *
from migen.fhdl.specials import Tristate
from migen.fhdl import verilog from migen.fhdl import verilog
n = 6 n = 6
@ -7,5 +8,5 @@ o = Signal(n)
oe = Signal() oe = Signal()
i = Signal(n) i = Signal(n)
f = Fragment(tristates={Tristate(pad, o, oe, i)}) f = Fragment(specials={Tristate(pad, o, oe, i)})
print(verilog.convert(f, ios={pad, o, oe, i})) print(verilog.convert(f, ios={pad, o, oe, i}))

View file

@ -7,6 +7,7 @@ from migen.uio.ioo import UnifiedIOSimulation
from migen.pytholite.transel import Register from migen.pytholite.transel import Register
from migen.pytholite.compiler import make_pytholite from migen.pytholite.compiler import make_pytholite
from migen.sim.generic import Simulator from migen.sim.generic import Simulator
from migen.fhdl.specials import Memory
from migen.fhdl import verilog from migen.fhdl import verilog
layout = [("r", 32)] layout = [("r", 32)]

View file

@ -2,6 +2,7 @@
# License: GPLv3 with additional permissions (see README). # License: GPLv3 with additional permissions (see README).
from migen.fhdl.structure import * from migen.fhdl.structure import *
from migen.fhdl.specials import Memory
from migen.sim.generic import Simulator from migen.sim.generic import Simulator
class Mem: class Mem:
@ -24,7 +25,7 @@ class Mem:
s.interrupt = True s.interrupt = True
def get_fragment(self): def get_fragment(self):
return Fragment(memories=[self.mem], sim=[self.do_simulation]) return Fragment(specials={self.mem}, sim=[self.do_simulation])
def main(): def main():
dut = Mem() dut = Mem()

View file

@ -1,6 +1,7 @@
# Simple Processor Interface # Simple Processor Interface
from migen.fhdl.structure import * from migen.fhdl.structure import *
from migen.fhdl.specials import Memory
from migen.bank.description import * from migen.bank.description import *
from migen.flow.actor import * from migen.flow.actor import *
@ -117,4 +118,4 @@ class Collector(Actor):
self._reg_rd.field.w.eq(rp.dat_r) self._reg_rd.field.w.eq(rp.dat_r)
] ]
return Fragment(comb, memories=[mem]) return Fragment(comb, specials={mem})

View file

@ -1,4 +1,5 @@
from migen.fhdl.structure import * from migen.fhdl.structure import *
from migen.fhdl.specials import Memory
from migen.bus.simple import * from migen.bus.simple import *
from migen.bus.transactions import * from migen.bus.transactions import *
from migen.sim.generic import PureSimulable from migen.sim.generic import PureSimulable
@ -97,4 +98,4 @@ class SRAM:
pv = self._page.field.r pv = self._page.field.r
comb.append(port.adr.eq(Cat(self.bus.adr[:len(port.adr)-len(pv)], pv))) comb.append(port.adr.eq(Cat(self.bus.adr[:len(port.adr)-len(pv)], pv)))
return Fragment(comb, sync, memories=[self.mem]) return Fragment(comb, sync, specials={self.mem})

View file

@ -1,4 +1,5 @@
from migen.fhdl.structure import * from migen.fhdl.structure import *
from migen.fhdl.specials import Memory
from migen.corelogic import roundrobin from migen.corelogic import roundrobin
from migen.corelogic.misc import optree from migen.corelogic.misc import optree
from migen.bus.simple import * from migen.bus.simple import *
@ -228,4 +229,4 @@ class SRAM:
self.bus.ack.eq(1) self.bus.ack.eq(1)
) )
] ]
return Fragment(comb, sync, memories=[self.mem]) return Fragment(comb, sync, specials={self.mem})

View file

@ -1,5 +1,6 @@
from migen.bus import wishbone
from migen.fhdl.structure import * from migen.fhdl.structure import *
from migen.fhdl.specials import Memory
from migen.bus import wishbone
from migen.corelogic.fsm import FSM from migen.corelogic.fsm import FSM
from migen.corelogic.misc import split, displacer, chooser from migen.corelogic.misc import split, displacer, chooser
from migen.corelogic.record import Record from migen.corelogic.record import Record
@ -136,5 +137,5 @@ class WB2ASMI:
fsm.next_state(fsm.TEST_HIT) fsm.next_state(fsm.TEST_HIT)
) )
return Fragment(comb, sync, memories=[data_mem, tag_mem]) \ return Fragment(comb, sync, specials={data_mem, tag_mem}) \
+ fsm.get_fragment() + fsm.get_fragment()

View file

@ -131,13 +131,10 @@ class Namespace:
self.pnd = pnd self.pnd = pnd
def get_name(self, sig): def get_name(self, sig):
if isinstance(sig, Memory): if sig.name_override is not None:
sig_name = "mem" sig_name = sig.name_override
else: else:
if sig.name_override is not None: sig_name = self.pnd[sig]
sig_name = sig.name_override
else:
sig_name = self.pnd[sig]
try: try:
n = self.sigs[sig] n = self.sigs[sig]
except KeyError: except KeyError:

311
migen/fhdl/specials.py Normal file
View file

@ -0,0 +1,311 @@
from migen.fhdl.structure import *
from migen.fhdl.tools import list_signals, value_bits_sign
from migen.fhdl.verilog import _printexpr as verilog_printexpr
class Special(HUID):
def rename_clock_domain(self):
pass
def get_clock_domains(self):
return set()
class Tristate(Special):
def __init__(self, target, o, oe, i=None):
Special.__init__(self)
self.target = target
self.o = o
self.oe = oe
self.i = i
def list_ios(self, ins, outs, inouts):
r = set()
if inouts:
r.update(list_signals(self.target))
if ins:
r.update(list_signals(self.o))
r.update(list_signals(self.oe))
if outs:
r.update(list_signals(self.i))
return r
@staticmethod
def emit_verilog(tristate, ns, clock_domains):
def pe(e):
return verilog_printexpr(ns, e)[0]
w, s = value_bits_sign(tristate.target)
r = "assign " + pe(tristate.target) + " = " \
+ pe(tristate.oe) + " ? " + pe(tristate.o) \
+ " : " + str(w) + "'bz;\n"
if tristate.i is not None:
r += "assign " + pe(tristate.i) + " = " + pe(tristate.target) + ";\n"
r += "\n"
return r
class TSTriple:
def __init__(self, bits_sign=None, min=None, max=None, reset_o=0, reset_oe=0):
self.o = Signal(bits_sign, min=min, max=max, reset=reset_o)
self.oe = Signal(reset=reset_oe)
self.i = Signal(bits_sign, min=min, max=max)
def get_tristate(self, target):
return Tristate(target, self.o, self.oe, self.i)
class Instance(Special):
def __init__(self, of, *items, name=""):
Special.__init__(self)
self.of = of
if name:
self.name_override = name
else:
self.name_override = of
self.items = items
class _IO:
def __init__(self, name, expr=None):
self.name = name
if expr is None:
expr = Signal()
self.expr = expr
class Input(_IO):
pass
class Output(_IO):
pass
class InOut(_IO):
pass
class Parameter:
def __init__(self, name, value):
self.name = name
self.value = value
class _CR:
def __init__(self, name_inst, domain="sys", invert=False):
self.name_inst = name_inst
self.domain = domain
self.invert = invert
class ClockPort(_CR):
pass
class ResetPort(_CR):
pass
def get_io(self, name):
for item in self.items:
if isinstance(item, Instance._IO) and item.name == name:
return item.expr
def rename_clock_domain(self):
for cr in filter(lambda x: isinstance(x, Instance._CR), self.items):
if cr.domain == old:
cr.domain = new
def get_clock_domains(self):
return set(cr.domain
for cr in filter(lambda x: isinstance(x, Instance._CR), self.items))
def list_ios(self, ins, outs, inouts):
subsets = [list_signals(item.expr) for item in filter(lambda x:
(ins and isinstance(x, Instance.Input))
or (outs and isinstance(x, Instance.Output))
or (inouts and isinstance(x, Instance.InOut)),
self.items)]
if subsets:
return set.union(*subsets)
else:
return set()
@staticmethod
def emit_verilog(instance, ns, clock_domains):
r = instance.of + " "
parameters = list(filter(lambda i: isinstance(i, Instance.Parameter), instance.items))
if parameters:
r += "#(\n"
firstp = True
for p in parameters:
if not firstp:
r += ",\n"
firstp = False
r += "\t." + p.name + "("
if isinstance(p.value, (int, bool)):
r += _printintbool(p.value)[0]
elif isinstance(p.value, float):
r += str(p.value)
elif isinstance(p.value, str):
r += "\"" + p.value + "\""
else:
raise TypeError
r += ")"
r += "\n) "
r += ns.get_name(instance)
if parameters: r += " "
r += "(\n"
firstp = True
for p in instance.items:
if isinstance(p, Instance._IO):
name_inst = p.name
name_design = verilog_printexpr(ns, p.expr)[0]
elif isinstance(p, Instance.ClockPort):
name_inst = p.name_inst
name_design = ns.get_name(clock_domains[p.domain].clk)
if p.invert:
name_design = "~" + name_design
elif isinstance(p, Instance.ResetPort):
name_inst = p.name_inst
name_design = ns.get_name(clock_domains[p.domain].rst)
else:
continue
if not firstp:
r += ",\n"
firstp = False
r += "\t." + name_inst + "(" + name_design + ")"
if not firstp:
r += "\n"
r += ");\n\n"
return r
(READ_FIRST, WRITE_FIRST, NO_CHANGE) = range(3)
class _MemoryPort:
def __init__(self, adr, dat_r, we=None, dat_w=None,
async_read=False, re=None, we_granularity=0, mode=WRITE_FIRST,
clock_domain="sys"):
self.adr = adr
self.dat_r = dat_r
self.we = we
self.dat_w = dat_w
self.async_read = async_read
self.re = re
self.we_granularity = we_granularity
self.mode = mode
self.clock_domain = clock_domain
class Memory(Special):
def __init__(self, width, depth, init=None):
Special.__init__(self)
self.width = width
self.depth = depth
self.ports = []
self.init = init
def get_port(self, write_capable=False, async_read=False,
has_re=False, we_granularity=0, mode=WRITE_FIRST,
clock_domain="sys"):
if we_granularity >= self.width:
we_granularity = 0
adr = Signal(max=self.depth)
dat_r = Signal(self.width)
if write_capable:
if we_granularity:
we = Signal(self.width//we_granularity)
else:
we = Signal()
dat_w = Signal(self.width)
else:
we = None
dat_w = None
if has_re:
re = Signal()
else:
re = None
mp = _MemoryPort(adr, dat_r, we, dat_w,
async_read, re, we_granularity, mode,
clock_domain)
self.ports.append(mp)
return mp
def rename_clock_domain(self):
for port in self.ports:
if port.clock_domain == old:
port.clock_domain = new
def get_clock_domains(self):
return set(port.clock_domain for port in self.ports)
def list_ios(self, ins, outs, inouts):
s = set()
def add(*sigs):
for sig in sigs:
if sig is not None:
s.add(sig)
for p in self.ports:
if ins:
add(p.adr, p.we, p.dat_w, p.re)
if outs:
add(p.dat_r)
return s
name_override = "mem"
@staticmethod
def emit_verilog(memory, ns, clock_domains):
r = ""
gn = ns.get_name # usable instead of verilog_printexpr as ports contain only signals
adrbits = bits_for(memory.depth-1)
r += "reg [" + str(memory.width-1) + ":0] " \
+ gn(memory) \
+ "[0:" + str(memory.depth-1) + "];\n"
adr_regs = {}
data_regs = {}
for port in memory.ports:
if not port.async_read:
if port.mode == WRITE_FIRST and port.we is not None:
adr_reg = Signal(name_override="memadr")
r += "reg [" + str(adrbits-1) + ":0] " \
+ gn(adr_reg) + ";\n"
adr_regs[id(port)] = adr_reg
else:
data_reg = Signal(name_override="memdat")
r += "reg [" + str(memory.width-1) + ":0] " \
+ gn(data_reg) + ";\n"
data_regs[id(port)] = data_reg
for port in memory.ports:
r += "always @(posedge " + gn(clock_domains[port.clock_domain].clk) + ") begin\n"
if port.we is not None:
if port.we_granularity:
n = memory.width//port.we_granularity
for i in range(n):
m = i*port.we_granularity
M = (i+1)*port.we_granularity-1
sl = "[" + str(M) + ":" + str(m) + "]"
r += "\tif (" + gn(port.we) + "[" + str(i) + "])\n"
r += "\t\t" + gn(memory) + "[" + gn(port.adr) + "]" + sl + " <= " + gn(port.dat_w) + sl + ";\n"
else:
r += "\tif (" + gn(port.we) + ")\n"
r += "\t\t" + gn(memory) + "[" + gn(port.adr) + "] <= " + gn(port.dat_w) + ";\n"
if not port.async_read:
if port.mode == WRITE_FIRST and port.we is not None:
rd = "\t" + gn(adr_regs[id(port)]) + " <= " + gn(port.adr) + ";\n"
else:
bassign = gn(data_regs[id(port)]) + " <= " + gn(memory) + "[" + gn(port.adr) + "];\n"
if port.mode == READ_FIRST or port.we is None:
rd = "\t" + bassign
elif port.mode == NO_CHANGE:
rd = "\tif (!" + gn(port.we) + ")\n" \
+ "\t\t" + bassign
if port.re is None:
r += rd
else:
r += "\tif (" + gn(port.re) + ")\n"
r += "\t" + rd.replace("\n\t", "\n\t\t")
r += "end\n\n"
for port in memory.ports:
if port.async_read:
r += "assign " + gn(port.dat_r) + " = " + gn(memory) + "[" + gn(port.adr) + "];\n"
else:
if port.mode == WRITE_FIRST and port.we is not None:
r += "assign " + gn(port.dat_r) + " = " + gn(memory) + "[" + gn(adr_regs[id(port)]) + "];\n"
else:
r += "assign " + gn(port.dat_r) + " = " + gn(data_regs[id(port)]) + ";\n"
r += "\n"
if memory.init is not None:
r += "initial begin\n"
for i, c in enumerate(memory.init):
r += "\t" + gn(memory) + "[" + str(i) + "] <= " + str(memory.width) + "'d" + str(c) + ";\n"
r += "end\n\n"
return r

View file

@ -229,126 +229,11 @@ class Array(list):
else: else:
return list.__getitem__(self, key) return list.__getitem__(self, key)
class Tristate:
def __init__(self, target, o, oe, i=None):
self.target = target
self.o = o
self.oe = oe
self.i = i
class TSTriple:
def __init__(self, bits_sign=None, min=None, max=None, reset_o=0, reset_oe=0):
self.o = Signal(bits_sign, min=min, max=max, reset=reset_o)
self.oe = Signal(reset=reset_oe)
self.i = Signal(bits_sign, min=min, max=max)
def get_tristate(self, target):
return Tristate(target, self.o, self.oe, self.i)
# extras
class Instance(HUID):
def __init__(self, of, *items, name=""):
HUID.__init__(self)
self.of = of
if name:
self.name_override = name
else:
self.name_override = of
self.items = items
class _IO:
def __init__(self, name, expr=None):
self.name = name
if expr is None:
expr = Signal()
self.expr = expr
class Input(_IO):
pass
class Output(_IO):
pass
class InOut(_IO):
pass
class Parameter:
def __init__(self, name, value):
self.name = name
self.value = value
class _CR:
def __init__(self, name_inst, domain="sys", invert=False):
self.name_inst = name_inst
self.domain = domain
self.invert = invert
class ClockPort(_CR):
pass
class ResetPort(_CR):
pass
def get_io(self, name):
for item in self.items:
if isinstance(item, Instance._IO) and item.name == name:
return item.expr
(READ_FIRST, WRITE_FIRST, NO_CHANGE) = range(3)
class _MemoryPort:
def __init__(self, adr, dat_r, we=None, dat_w=None,
async_read=False, re=None, we_granularity=0, mode=WRITE_FIRST,
clock_domain="sys"):
self.adr = adr
self.dat_r = dat_r
self.we = we
self.dat_w = dat_w
self.async_read = async_read
self.re = re
self.we_granularity = we_granularity
self.mode = mode
self.clock_domain = clock_domain
class Memory(HUID):
def __init__(self, width, depth, init=None):
HUID.__init__(self)
self.width = width
self.depth = depth
self.ports = []
self.init = init
def get_port(self, write_capable=False, async_read=False,
has_re=False, we_granularity=0, mode=WRITE_FIRST,
clock_domain="sys"):
if we_granularity >= self.width:
we_granularity = 0
adr = Signal(max=self.depth)
dat_r = Signal(self.width)
if write_capable:
if we_granularity:
we = Signal(self.width//we_granularity)
else:
we = Signal()
dat_w = Signal(self.width)
else:
we = None
dat_w = None
if has_re:
re = Signal()
else:
re = None
mp = _MemoryPort(adr, dat_r, we, dat_w,
async_read, re, we_granularity, mode,
clock_domain)
self.ports.append(mp)
return mp
#
class Fragment: class Fragment:
def __init__(self, comb=None, sync=None, instances=None, tristates=None, memories=None, sim=None): def __init__(self, comb=None, sync=None, specials=None, sim=None):
if comb is None: comb = [] if comb is None: comb = []
if sync is None: sync = dict() if sync is None: sync = dict()
if instances is None: instances = set() if specials is None: specials = set()
if tristates is None: tristates = set()
if memories is None: memories = set()
if sim is None: sim = [] if sim is None: sim = []
if isinstance(sync, list): if isinstance(sync, list):
@ -356,9 +241,7 @@ class Fragment:
self.comb = comb self.comb = comb
self.sync = sync self.sync = sync
self.instances = set(instances) self.specials = set(specials)
self.tristates = set(tristates)
self.memories = set(memories)
self.sim = sim self.sim = sim
def __add__(self, other): def __add__(self, other):
@ -368,32 +251,14 @@ class Fragment:
for k, v in other.sync.items(): for k, v in other.sync.items():
newsync[k].extend(v) newsync[k].extend(v)
return Fragment(self.comb + other.comb, newsync, return Fragment(self.comb + other.comb, newsync,
self.instances | other.instances, self.specials | other.specials,
self.tristates | other.tristates,
self.memories | other.memories,
self.sim + other.sim) self.sim + other.sim)
def rename_clock_domain(self, old, new): def rename_clock_domain(self, old, new):
self.sync["new"] = self.sync["old"] self.sync["new"] = self.sync["old"]
del self.sync["old"] del self.sync["old"]
for inst in self.instances: for special in self.specials:
for cr in filter(lambda x: isinstance(x, Instance._CR), inst.items): special.rename_clock_domain(old, new)
if cr.domain == old:
cr.domain = new
for mem in self.memories:
for port in mem.ports:
if port.clock_domain == old:
port.clock_domain = new
def get_clock_domains(self):
r = set(self.sync.keys())
r |= set(cr.domain
for inst in self.instances
for cr in filter(lambda x: isinstance(x, Instance._CR), inst.items))
r |= set(port.clock_domain
for mem in self.memories
for port in mem.ports)
return r
def call_sim(self, simulator): def call_sim(self, simulator):
for s in self.sim: for s in self.sim:

View file

@ -56,68 +56,17 @@ def group_by_targets(sl):
groups.append((targets, [statement])) groups.append((targets, [statement]))
return groups return groups
def list_inst_ios(i, ins, outs, inouts): def list_special_ios(f, ins, outs, inouts):
if isinstance(i, Fragment): r = set()
return list_inst_ios(i.instances, ins, outs, inouts) for special in f.specials:
elif isinstance(i, set): r |= special.list_ios(ins, outs, inouts)
if i: return r
return set.union(*(list_inst_ios(e, ins, outs, inouts) for e in i))
else:
return set()
elif isinstance(i, Instance):
subsets = [list_signals(item.expr) for item in filter(lambda x:
(ins and isinstance(x, Instance.Input))
or (outs and isinstance(x, Instance.Output))
or (inouts and isinstance(x, Instance.InOut)),
i.items)]
if subsets:
return set.union(*subsets)
else:
return set()
else:
return set()
def list_tristate_ios(i, ins, outs, inouts): def list_clock_domains(f):
if isinstance(i, Fragment): r = set(f.sync.keys())
return list_tristate_ios(i.tristates, ins, outs, inouts) for special in f.specials:
elif isinstance(i, set): r |= special.get_clock_domains()
if i: return r
return set.union(*(list_tristate_ios(e, ins, outs, inouts) for e in i))
else:
return set()
elif isinstance(i, Tristate):
r = set()
if inouts:
r.update(list_signals(i.target))
if ins:
r.update(list_signals(i.o))
r.update(list_signals(i.oe))
if outs:
r.update(list_signals(i.i))
return r
else:
return set()
def list_it_ios(i, ins, outs, inouts):
return list_inst_ios(i, ins, outs, inouts) \
| list_tristate_ios(i, ins, outs, inouts)
def list_mem_ios(m, ins, outs):
if isinstance(m, Fragment):
return list_mem_ios(m.memories, ins, outs)
else:
s = set()
def add(*sigs):
for sig in sigs:
if sig is not None:
s.add(sig)
for x in m:
for p in x.ports:
if ins:
add(p.adr, p.we, p.dat_w, p.re)
if outs:
add(p.dat_r)
return s
def is_variable(node): def is_variable(node):
if isinstance(node, Signal): if isinstance(node, Signal):

View file

@ -5,7 +5,6 @@ from migen.fhdl.structure import *
from migen.fhdl.structure import _Operator, _Slice, _Assign from migen.fhdl.structure import _Operator, _Slice, _Assign
from migen.fhdl.tools import * from migen.fhdl.tools import *
from migen.fhdl.namer import Namespace, build_namespace from migen.fhdl.namer import Namespace, build_namespace
from migen.fhdl import verilog_behavioral as behavioral
def _printsig(ns, s): def _printsig(ns, s):
if s.signed: if s.signed:
@ -135,9 +134,9 @@ def _list_comb_wires(f):
return r return r
def _printheader(f, ios, name, ns): def _printheader(f, ios, name, ns):
sigs = list_signals(f) | list_it_ios(f, True, True, True) | list_mem_ios(f, True, True) sigs = list_signals(f) | list_special_ios(f, True, True, True)
it_mem_outs = list_it_ios(f, False, True, False) | list_mem_ios(f, False, True) it_mem_outs = list_special_ios(f, False, True, False)
inouts = list_it_ios(f, False, False, True) inouts = list_special_ios(f, False, False, True)
targets = list_targets(f) | it_mem_outs targets = list_targets(f) | it_mem_outs
wires = _list_comb_wires(f) | it_mem_outs wires = _list_comb_wires(f) | it_mem_outs
r = "module " + name + "(\n" r = "module " + name + "(\n"
@ -209,66 +208,10 @@ def _printsync(f, ns, clock_domains):
r += "end\n\n" r += "end\n\n"
return r return r
def _printinstances(f, ns, clock_domains): def _printspecials(f, ns, clock_domains):
r = "" r = ""
for x in f.instances: for special in sorted(f.specials, key=lambda x: x.huid):
parameters = list(filter(lambda i: isinstance(i, Instance.Parameter), x.items)) r += special.emit_verilog(special, ns, clock_domains)
r += x.of + " "
if parameters:
r += "#(\n"
firstp = True
for p in parameters:
if not firstp:
r += ",\n"
firstp = False
r += "\t." + p.name + "("
if isinstance(p.value, (int, bool)):
r += _printintbool(p.value)[0]
elif isinstance(p.value, float):
r += str(p.value)
elif isinstance(p.value, str):
r += "\"" + p.value + "\""
else:
raise TypeError
r += ")"
r += "\n) "
r += ns.get_name(x)
if parameters: r += " "
r += "(\n"
firstp = True
for p in x.items:
if isinstance(p, Instance._IO):
name_inst = p.name
name_design = _printexpr(ns, p.expr)[0]
elif isinstance(p, Instance.ClockPort):
name_inst = p.name_inst
name_design = ns.get_name(clock_domains[p.domain].clk)
if p.invert:
name_design = "~" + name_design
elif isinstance(p, Instance.ResetPort):
name_inst = p.name_inst
name_design = ns.get_name(clock_domains[p.domain].rst)
else:
continue
if not firstp:
r += ",\n"
firstp = False
r += "\t." + name_inst + "(" + name_design + ")"
if not firstp:
r += "\n"
r += ");\n\n"
return r
def _printtristates(f, ns, handler):
r = ""
for tristate in f.tristates:
r += handler(tristate, ns)
return r
def _printmemories(f, ns, handler, clock_domains):
r = ""
for memory in f.memories:
r += handler(memory, ns, clock_domains)
return r return r
def _printinit(f, ios, ns): def _printinit(f, ios, ns):
@ -276,8 +219,7 @@ def _printinit(f, ios, ns):
signals = list_signals(f) \ signals = list_signals(f) \
- ios \ - ios \
- list_targets(f) \ - list_targets(f) \
- list_it_ios(f, False, True, False) \ - list_special_ios(f, False, True, False)
- list_mem_ios(f, False, True)
if signals: if signals:
r += "initial begin\n" r += "initial begin\n"
for s in sorted(signals, key=lambda x: x.huid): for s in sorted(signals, key=lambda x: x.huid):
@ -288,14 +230,12 @@ def _printinit(f, ios, ns):
def convert(f, ios=None, name="top", def convert(f, ios=None, name="top",
clock_domains=None, clock_domains=None,
return_ns=False, return_ns=False,
memory_handler=behavioral.mem_handler,
tristate_handler=behavioral.tristate_handler,
display_run=False): display_run=False):
if ios is None: if ios is None:
ios = set() ios = set()
if clock_domains is None: if clock_domains is None:
clock_domains = dict() clock_domains = dict()
for d in f.get_clock_domains(): for d in list_clock_domains(f):
cd = ClockDomain(d) cd = ClockDomain(d)
clock_domains[d] = cd clock_domains[d] = cd
ios.add(cd.clk) ios.add(cd.clk)
@ -304,17 +244,14 @@ def convert(f, ios=None, name="top",
f = lower_arrays(f) f = lower_arrays(f)
ns = build_namespace(list_signals(f) \ ns = build_namespace(list_signals(f) \
| list_it_ios(f, True, True, True) \ | list_special_ios(f, True, True, True) \
| list_mem_ios(f, True, True) \
| ios) | ios)
r = "/* Machine-generated using Migen */\n" r = "/* Machine-generated using Migen */\n"
r += _printheader(f, ios, name, ns) r += _printheader(f, ios, name, ns)
r += _printcomb(f, ns, display_run) r += _printcomb(f, ns, display_run)
r += _printsync(f, ns, clock_domains) r += _printsync(f, ns, clock_domains)
r += _printinstances(f, ns, clock_domains) r += _printspecials(f, ns, clock_domains)
r += _printtristates(f, ns, tristate_handler)
r += _printmemories(f, ns, memory_handler, clock_domains)
r += _printinit(f, ios, ns) r += _printinit(f, ios, ns)
r += "endmodule\n" r += "endmodule\n"

View file

@ -1,86 +0,0 @@
from migen.fhdl.structure import *
from migen.fhdl.tools import *
def mem_handler(memory, ns, clock_domains):
r = ""
gn = ns.get_name
adrbits = bits_for(memory.depth-1)
r += "reg [" + str(memory.width-1) + ":0] " \
+ gn(memory) \
+ "[0:" + str(memory.depth-1) + "];\n"
adr_regs = {}
data_regs = {}
for port in memory.ports:
if not port.async_read:
if port.mode == WRITE_FIRST and port.we is not None:
adr_reg = Signal(name_override="memadr")
r += "reg [" + str(adrbits-1) + ":0] " \
+ gn(adr_reg) + ";\n"
adr_regs[id(port)] = adr_reg
else:
data_reg = Signal(name_override="memdat")
r += "reg [" + str(memory.width-1) + ":0] " \
+ gn(data_reg) + ";\n"
data_regs[id(port)] = data_reg
for port in memory.ports:
r += "always @(posedge " + gn(clock_domains[port.clock_domain].clk) + ") begin\n"
if port.we is not None:
if port.we_granularity:
n = memory.width//port.we_granularity
for i in range(n):
m = i*port.we_granularity
M = (i+1)*port.we_granularity-1
sl = "[" + str(M) + ":" + str(m) + "]"
r += "\tif (" + gn(port.we) + "[" + str(i) + "])\n"
r += "\t\t" + gn(memory) + "[" + gn(port.adr) + "]" + sl + " <= " + gn(port.dat_w) + sl + ";\n"
else:
r += "\tif (" + gn(port.we) + ")\n"
r += "\t\t" + gn(memory) + "[" + gn(port.adr) + "] <= " + gn(port.dat_w) + ";\n"
if not port.async_read:
if port.mode == WRITE_FIRST and port.we is not None:
rd = "\t" + gn(adr_regs[id(port)]) + " <= " + gn(port.adr) + ";\n"
else:
bassign = gn(data_regs[id(port)]) + " <= " + gn(memory) + "[" + gn(port.adr) + "];\n"
if port.mode == READ_FIRST or port.we is None:
rd = "\t" + bassign
elif port.mode == NO_CHANGE:
rd = "\tif (!" + gn(port.we) + ")\n" \
+ "\t\t" + bassign
if port.re is None:
r += rd
else:
r += "\tif (" + gn(port.re) + ")\n"
r += "\t" + rd.replace("\n\t", "\n\t\t")
r += "end\n\n"
for port in memory.ports:
if port.async_read:
r += "assign " + gn(port.dat_r) + " = " + gn(memory) + "[" + gn(port.adr) + "];\n"
else:
if port.mode == WRITE_FIRST and port.we is not None:
r += "assign " + gn(port.dat_r) + " = " + gn(memory) + "[" + gn(adr_regs[id(port)]) + "];\n"
else:
r += "assign " + gn(port.dat_r) + " = " + gn(data_regs[id(port)]) + ";\n"
r += "\n"
if memory.init is not None:
r += "initial begin\n"
for i, c in enumerate(memory.init):
r += "\t" + gn(memory) + "[" + str(i) + "] <= " + str(memory.width) + "'d" + str(c) + ";\n"
r += "end\n\n"
return r
def tristate_handler(tristate, ns):
gn = ns.get_name
w, s = value_bits_sign(tristate.target)
r = "assign " + gn(tristate.target) + " = " \
+ gn(tristate.oe) + " ? " + gn(tristate.o) \
+ " : " + str(w) + "'bz;\n"
if tristate.i is not None:
r += "assign " + gn(tristate.i) + " = " + gn(tristate.target) + ";\n"
r += "\n"
return r

View file

@ -2,6 +2,7 @@ import ast
from itertools import zip_longest from itertools import zip_longest
from migen.fhdl.structure import * from migen.fhdl.structure import *
from migen.fhdl.specials import Memory
from migen.uio.ioo import UnifiedIOObject from migen.uio.ioo import UnifiedIOObject
from migen.flow.actor import Source, Sink from migen.flow.actor import Source, Sink
from migen.flow.transactions import * from migen.flow.transactions import *

View file

@ -2,6 +2,7 @@
# License: GPLv3 with additional permissions (see README). # License: GPLv3 with additional permissions (see README).
from migen.fhdl.structure import * from migen.fhdl.structure import *
from migen.fhdl.specials import Memory
from migen.fhdl import verilog from migen.fhdl import verilog
from migen.sim.ipc import * from migen.sim.ipc import *
from migen.sim import icarus from migen.sim import icarus

View file

@ -1,4 +1,5 @@
from migen.fhdl.structure import * from migen.fhdl.structure import *
from migen.fhdl.specials import Memory
from migen.flow.actor import * from migen.flow.actor import *
from migen.flow.transactions import * from migen.flow.transactions import *
from migen.actorlib.sim import TokenExchanger from migen.actorlib.sim import TokenExchanger
@ -14,7 +15,7 @@ class UnifiedIOObject(Actor):
self._memories = set(v for v in self.buses.values() if isinstance(v, Memory)) self._memories = set(v for v in self.buses.values() if isinstance(v, Memory))
def get_fragment(self): def get_fragment(self):
return Fragment(memories=self._memories) return Fragment(specials={self._memories})
(_WAIT_COMPLETE, _WAIT_POLL) = range(2) (_WAIT_COMPLETE, _WAIT_POLL) = range(2)