mirror of
https://github.com/enjoy-digital/litex.git
synced 2025-01-04 09:52:26 -05:00
New 'specials' API
This commit is contained in:
parent
e82ea19cdc
commit
49cfba50fa
18 changed files with 406 additions and 412 deletions
|
@ -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("interrupt", self.interrupt),
|
||||||
Instance.Input("ext_break", 1),
|
#Instance.Input("ext_break", self.ext_break),
|
||||||
|
|
||||||
Instance.Output("I_ADR_O", 32),
|
Instance.Output("I_ADR_O", self._i_adr_o),
|
||||||
Instance.Output("I_DAT_O", 32),
|
Instance.Output("I_DAT_O", i.dat_w),
|
||||||
Instance.Output("I_SEL_O", 4),
|
Instance.Output("I_SEL_O", i.sel),
|
||||||
Instance.Output("I_CYC_O", 1),
|
Instance.Output("I_CYC_O", i.cyc),
|
||||||
Instance.Output("I_STB_O", 1),
|
Instance.Output("I_STB_O", i.stb),
|
||||||
Instance.Output("I_WE_O", 1),
|
Instance.Output("I_WE_O", i.we),
|
||||||
Instance.Output("I_CTI_O", 3),
|
Instance.Output("I_CTI_O", i.cti),
|
||||||
Instance.Output("I_LOCK_O", 1),
|
Instance.Output("I_LOCK_O"),
|
||||||
Instance.Output("I_BTE_O", 1),
|
Instance.Output("I_BTE_O", i.bte),
|
||||||
Instance.Input("I_DAT_I", 32),
|
Instance.Input("I_DAT_I", i.dat_r),
|
||||||
Instance.Input("I_ACK_I", 1),
|
Instance.Input("I_ACK_I", i.ack),
|
||||||
Instance.Input("I_ERR_I", 1),
|
Instance.Input("I_ERR_I", i.err),
|
||||||
Instance.Input("I_RTY_I", 1),
|
Instance.Input("I_RTY_I", 0),
|
||||||
|
|
||||||
Instance.Output("D_ADR_O", 32),
|
Instance.Output("D_ADR_O", self._d_adr_o),
|
||||||
Instance.Output("D_DAT_O", 32),
|
Instance.Output("D_DAT_O", d.dat_w),
|
||||||
Instance.Output("D_SEL_O", 4),
|
Instance.Output("D_SEL_O", d.sel),
|
||||||
Instance.Output("D_CYC_O", 1),
|
Instance.Output("D_CYC_O", d.cyc),
|
||||||
Instance.Output("D_STB_O", 1),
|
Instance.Output("D_STB_O", d.stb),
|
||||||
Instance.Output("D_WE_O", 1),
|
Instance.Output("D_WE_O", d.we),
|
||||||
Instance.Output("D_CTI_O", 3),
|
Instance.Output("D_CTI_O", d.cti),
|
||||||
Instance.Output("D_LOCK_O", 1),
|
Instance.Output("D_LOCK_O"),
|
||||||
Instance.Output("D_BTE_O", 1),
|
Instance.Output("D_BTE_O", d.bte),
|
||||||
Instance.Input("D_DAT_I", 32),
|
Instance.Input("D_DAT_I", d.dat_r),
|
||||||
Instance.Input("D_ACK_I", 1),
|
Instance.Input("D_ACK_I", d.ack),
|
||||||
Instance.Input("D_ERR_I", 1),
|
Instance.Input("D_ERR_I", d.err),
|
||||||
Instance.Input("D_RTY_I", 1),
|
Instance.Input("D_RTY_I", 0))
|
||||||
|
|
||||||
name="lm32")
|
|
||||||
|
|
||||||
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}))
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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}))
|
||||||
|
|
|
@ -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)]
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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})
|
||||||
|
|
|
@ -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})
|
||||||
|
|
|
@ -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})
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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
311
migen/fhdl/specials.py
Normal 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
|
|
@ -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:
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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"
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
|
@ -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 *
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue