New 'specials' API
authorSebastien Bourdeauducq <sebastien@milkymist.org>
Fri, 22 Feb 2013 16:56:35 +0000 (17:56 +0100)
committerSebastien Bourdeauducq <sebastien@milkymist.org>
Fri, 22 Feb 2013 16:56:35 +0000 (17:56 +0100)
18 files changed:
examples/basic/lm32_inst.py
examples/basic/memory.py
examples/basic/tristate.py
examples/pytholite/uio.py
examples/sim/memory.py
migen/actorlib/spi.py
migen/bus/csr.py
migen/bus/wishbone.py
migen/bus/wishbone2asmi.py
migen/fhdl/namer.py
migen/fhdl/specials.py [new file with mode: 0644]
migen/fhdl/structure.py
migen/fhdl/tools.py
migen/fhdl/verilog.py
migen/fhdl/verilog_behavioral.py [deleted file]
migen/pytholite/io.py
migen/sim/generic.py
migen/uio/ioo.py

index 8711dae3d4a408f2412a36ecffce29568e4cc37a..1ea05a057244559fd237289b936d9ee57dfec3f9 100644 (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.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.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),
+                       Instance.Input("interrupt", self.interrupt),
+                       #Instance.Input("ext_break", self.ext_break),
+               
+                       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),
                        
-                       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}))
index 3d0aab457d9a0bcf5a8008a973dc386c9cfbf473..edfedf23794d3d96f0171746da8d40a6d42e94b6 100644 (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)
index 3886b969686bb90abfefaa71be6d0f68f3ca2717..375524bf1abd8c420d0b41cdd13173f585959c57 100644 (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}))
index 42e66463e50d7918f2aa47016571d0c6b61645a8..01b52e11e51aff23604dc01bf54c1cffbe040b76 100644 (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)]
index 7d66f234d544933c219a2b66b78f53f981058c91..4433017907aee9a7125a91d553f210945fe96f25 100644 (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()
index 674c36c3565d1ef18f528f27adfa96724489cf3d..649d24bd049c938e7d0dfed93dd377de58f6dfa4 100644 (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})
index 6a75d7cd33a0701a5069bae72a4421ef69d4debc..264c63c001fd033227dd0e3594afecb03614aaf4 100644 (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})
index efdf09adc9f6ce837d51851c7fe9c089c268cdfb..fb7ec125d7425adac0e484c393d21507806c0a25 100644 (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})
index e19f9f98d62a845a3a6bf6fb17c91cd5c7efb183..0fccefccd01f8d3d6ac2bacfa5df4dae44c79b98 100644 (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()
index 4f5e317e56a6707568c886994d14701f80e5b071..d27f303feddc4ad306b5935cf16e59d4350162fb 100644 (file)
@@ -131,13 +131,10 @@ class Namespace:
                self.pnd = pnd
        
        def get_name(self, sig):
-               if isinstance(sig, Memory):
-                       sig_name = "mem"
+               if sig.name_override is not None:
+                       sig_name = sig.name_override
                else:
-                       if sig.name_override is not None:
-                               sig_name = sig.name_override
-                       else:
-                               sig_name = self.pnd[sig]
+                       sig_name = self.pnd[sig]
                try:
                        n = self.sigs[sig]
                except KeyError:
diff --git a/migen/fhdl/specials.py b/migen/fhdl/specials.py
new file mode 100644 (file)
index 0000000..829601d
--- /dev/null
@@ -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
index 321347c0216abd8ae5958339d3b372e7c90a766c..8052fdffbbc700e473247c8dab0f8ecd2643ec15 100644 (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:
index 02564925d6b00fca312422a04d4719fc99c9d0e3..62e1183e3e2e3876d22fd13b06c9d2dbcebea506 100644 (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_special_ios(f, ins, outs, inouts):
+       r = set()
+       for special in f.specials:
+               r |= special.list_ios(ins, outs, inouts)
+       return r
 
-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):
-               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 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):
index 0e0821cdc9b326c5cf77fe842395ec40264d6966..9e84b31a031fabf23529808542aa4c9670621f3b 100644 (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"
 
diff --git a/migen/fhdl/verilog_behavioral.py b/migen/fhdl/verilog_behavioral.py
deleted file mode 100644 (file)
index 2835af2..0000000
+++ /dev/null
@@ -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
index 943e972626226d38ae41f45d49112fffda1fb2eb..63c92a60b9efe7e8a77c86cc1c52bce4c0cce1f9 100644 (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 *
index cc72769f4be28b845f35947be081d0d47cd72774..178366128e358883e0331bb0e21e84a49ce081be 100644 (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
index 5dfdcba0c9054e9be1f99b9588b114e063d1e32f..1393d915058f028c1147d722bb66395f1f25add3 100644 (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)