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.specials import Instance
from migen.bus import wishbone
from migen.fhdl import verilog
class LM32:
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.ResetPort("rst_i"),
Instance.Input("interrupt", 32),
Instance.Input("ext_break", 1),
Instance.Input("interrupt", self.interrupt),
#Instance.Input("ext_break", self.ext_break),
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("I_ADR_O", self._i_adr_o),
Instance.Output("I_DAT_O", i.dat_w),
Instance.Output("I_SEL_O", i.sel),
Instance.Output("I_CYC_O", i.cyc),
Instance.Output("I_STB_O", i.stb),
Instance.Output("I_WE_O", i.we),
Instance.Output("I_CTI_O", i.cti),
Instance.Output("I_LOCK_O"),
Instance.Output("I_BTE_O", i.bte),
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),
Instance.Output("D_ADR_O", 32),
Instance.Output("D_DAT_O", 32),
Instance.Output("D_SEL_O", 4),
Instance.Output("D_CYC_O", 1),
Instance.Output("D_STB_O", 1),
Instance.Output("D_WE_O", 1),
Instance.Output("D_CTI_O", 3),
Instance.Output("D_LOCK_O", 1),
Instance.Output("D_BTE_O", 1),
Instance.Input("D_DAT_I", 32),
Instance.Input("D_ACK_I", 1),
Instance.Input("D_ERR_I", 1),
Instance.Input("D_RTY_I", 1),
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):
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)]
frag = Fragment()
for cpu in cpus:
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
mem = Memory(32, 100, init=[5, 18, 32])
p1 = mem.get_port(write_capable=True, we_granularity=8)
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,
p2.adr, p2.dat_r, p2.re})
print(v)

View file

@ -1,4 +1,5 @@
from migen.fhdl.structure import *
from migen.fhdl.specials import Tristate
from migen.fhdl import verilog
n = 6
@ -7,5 +8,5 @@ o = Signal(n)
oe = Signal()
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}))

View file

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

View file

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

View file

@ -1,6 +1,7 @@
# Simple Processor Interface
from migen.fhdl.structure import *
from migen.fhdl.specials import Memory
from migen.bank.description import *
from migen.flow.actor import *
@ -117,4 +118,4 @@ class Collector(Actor):
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.specials import Memory
from migen.bus.simple import *
from migen.bus.transactions import *
from migen.sim.generic import PureSimulable
@ -97,4 +98,4 @@ class SRAM:
pv = self._page.field.r
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.specials import Memory
from migen.corelogic import roundrobin
from migen.corelogic.misc import optree
from migen.bus.simple import *
@ -228,4 +229,4 @@ class SRAM:
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.specials import Memory
from migen.bus import wishbone
from migen.corelogic.fsm import FSM
from migen.corelogic.misc import split, displacer, chooser
from migen.corelogic.record import Record
@ -136,5 +137,5 @@ class WB2ASMI:
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()

View file

@ -131,9 +131,6 @@ class Namespace:
self.pnd = pnd
def get_name(self, sig):
if isinstance(sig, Memory):
sig_name = "mem"
else:
if sig.name_override is not None:
sig_name = sig.name_override
else:

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:
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:
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 sync is None: sync = dict()
if instances is None: instances = set()
if tristates is None: tristates = set()
if memories is None: memories = set()
if specials is None: specials = set()
if sim is None: sim = []
if isinstance(sync, list):
@ -356,9 +241,7 @@ class Fragment:
self.comb = comb
self.sync = sync
self.instances = set(instances)
self.tristates = set(tristates)
self.memories = set(memories)
self.specials = set(specials)
self.sim = sim
def __add__(self, other):
@ -368,32 +251,14 @@ class Fragment:
for k, v in other.sync.items():
newsync[k].extend(v)
return Fragment(self.comb + other.comb, newsync,
self.instances | other.instances,
self.tristates | other.tristates,
self.memories | other.memories,
self.specials | other.specials,
self.sim + other.sim)
def rename_clock_domain(self, old, new):
self.sync["new"] = self.sync["old"]
del self.sync["old"]
for inst in self.instances:
for cr in filter(lambda x: isinstance(x, Instance._CR), inst.items):
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
for special in self.specials:
special.rename_clock_domain(old, new)
def call_sim(self, simulator):
for s in self.sim:

View file

@ -56,68 +56,17 @@ def group_by_targets(sl):
groups.append((targets, [statement]))
return groups
def list_inst_ios(i, ins, outs, inouts):
if isinstance(i, Fragment):
return list_inst_ios(i.instances, ins, outs, inouts)
elif isinstance(i, set):
if i:
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):
if isinstance(i, Fragment):
return list_tristate_ios(i.tristates, ins, outs, inouts)
elif isinstance(i, set):
if i:
return set.union(*(list_tristate_ios(e, ins, outs, inouts) for e in i))
else:
return set()
elif isinstance(i, Tristate):
def list_special_ios(f, ins, outs, inouts):
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))
for special in f.specials:
r |= special.list_ios(ins, outs, inouts)
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 list_clock_domains(f):
r = set(f.sync.keys())
for special in f.specials:
r |= special.get_clock_domains()
return r
def is_variable(node):
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.tools import *
from migen.fhdl.namer import Namespace, build_namespace
from migen.fhdl import verilog_behavioral as behavioral
def _printsig(ns, s):
if s.signed:
@ -135,9 +134,9 @@ def _list_comb_wires(f):
return r
def _printheader(f, ios, name, ns):
sigs = list_signals(f) | list_it_ios(f, True, True, True) | list_mem_ios(f, True, True)
it_mem_outs = list_it_ios(f, False, True, False) | list_mem_ios(f, False, True)
inouts = list_it_ios(f, False, False, True)
sigs = list_signals(f) | list_special_ios(f, True, True, True)
it_mem_outs = list_special_ios(f, False, True, False)
inouts = list_special_ios(f, False, False, True)
targets = list_targets(f) | it_mem_outs
wires = _list_comb_wires(f) | it_mem_outs
r = "module " + name + "(\n"
@ -209,66 +208,10 @@ def _printsync(f, ns, clock_domains):
r += "end\n\n"
return r
def _printinstances(f, ns, clock_domains):
def _printspecials(f, ns, clock_domains):
r = ""
for x in f.instances:
parameters = list(filter(lambda i: isinstance(i, Instance.Parameter), x.items))
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)
for special in sorted(f.specials, key=lambda x: x.huid):
r += special.emit_verilog(special, ns, clock_domains)
return r
def _printinit(f, ios, ns):
@ -276,8 +219,7 @@ def _printinit(f, ios, ns):
signals = list_signals(f) \
- ios \
- list_targets(f) \
- list_it_ios(f, False, True, False) \
- list_mem_ios(f, False, True)
- list_special_ios(f, False, True, False)
if signals:
r += "initial begin\n"
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",
clock_domains=None,
return_ns=False,
memory_handler=behavioral.mem_handler,
tristate_handler=behavioral.tristate_handler,
display_run=False):
if ios is None:
ios = set()
if clock_domains is None:
clock_domains = dict()
for d in f.get_clock_domains():
for d in list_clock_domains(f):
cd = ClockDomain(d)
clock_domains[d] = cd
ios.add(cd.clk)
@ -304,17 +244,14 @@ def convert(f, ios=None, name="top",
f = lower_arrays(f)
ns = build_namespace(list_signals(f) \
| list_it_ios(f, True, True, True) \
| list_mem_ios(f, True, True) \
| list_special_ios(f, True, True, True) \
| ios)
r = "/* Machine-generated using Migen */\n"
r += _printheader(f, ios, name, ns)
r += _printcomb(f, ns, display_run)
r += _printsync(f, ns, clock_domains)
r += _printinstances(f, ns, clock_domains)
r += _printtristates(f, ns, tristate_handler)
r += _printmemories(f, ns, memory_handler, clock_domains)
r += _printspecials(f, ns, clock_domains)
r += _printinit(f, ios, ns)
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 migen.fhdl.structure import *
from migen.fhdl.specials import Memory
from migen.uio.ioo import UnifiedIOObject
from migen.flow.actor import Source, Sink
from migen.flow.transactions import *

View file

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

View file

@ -1,4 +1,5 @@
from migen.fhdl.structure import *
from migen.fhdl.specials import Memory
from migen.flow.actor import *
from migen.flow.transactions import *
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))
def get_fragment(self):
return Fragment(memories=self._memories)
return Fragment(specials={self._memories})
(_WAIT_COMPLETE, _WAIT_POLL) = range(2)