add fabric compatibility mode
[soc.git] / src / soc / minerva / wishbone.py
index 91936b39bc06b833cc13e5e84130dc4e8ffca1dc..f249d5547330b632d0499f7917edca5dc15e259b 100644 (file)
@@ -1,9 +1,10 @@
 from nmigen import Array, Elaboratable, Module, Record, Signal
 from nmigen.hdl.rec import DIR_FANIN, DIR_FANOUT, DIR_NONE
 from nmigen.lib.coding import PriorityEncoder
+from nmigen.utils import log2_int
 
 
-__all__ = ["Cycle", "wishbone_layout", "WishboneArbiter"]
+__all__ = ["Cycle", "make_wb_layout", "WishboneArbiter"]
 
 
 class Cycle:
@@ -13,30 +14,48 @@ class Cycle:
     END       = 7
 
 
-wishbone_layout = [
-    ("adr",   30, DIR_FANOUT),
-    ("dat_w", 32, DIR_FANOUT),
-    ("dat_r", 32, DIR_FANIN),
-    ("sel",    4, DIR_FANOUT),
-    ("cyc",    1, DIR_FANOUT),
-    ("stb",    1, DIR_FANOUT),
-    ("ack",    1, DIR_FANIN),
-    ("we",     1, DIR_FANOUT),
-    ("cti",    3, DIR_FANOUT),
-    ("bte",    2, DIR_FANOUT),
-    ("err",    1, DIR_FANIN)
-]
+def make_wb_layout(spec, cti=True):
+    addr_wid, mask_wid, data_wid = spec.addr_wid, spec.mask_wid, spec.reg_wid
+    adr_lsbs = log2_int(mask_wid) # LSBs of addr covered by mask
+    badwid = spec.addr_wid-adr_lsbs    # MSBs (not covered by mask)
+    # test if microwatt compatibility is to be enabled
+    microwatt_compat = (hasattr(spec, "microwatt_compat") and
+                               (spec.microwatt_compat == True))
+    # test if fabric compatibility is to be enabled
+    fabric_compat = (hasattr(spec, "fabric_compat") and
+                               (spec.fabric_compat == True))
+
+    res = [
+    ("adr",   badwid  , DIR_FANOUT),
+    ("dat_w", data_wid, DIR_FANOUT),
+    ("dat_r", data_wid, DIR_FANIN),
+    ("sel",   mask_wid, DIR_FANOUT),
+    ("cyc",           1, DIR_FANOUT),
+    ("stb",           1, DIR_FANOUT),
+    ("ack",           1, DIR_FANIN),
+    ("we",            1, DIR_FANOUT),
+    ("err",           1, DIR_FANIN)
+    ]
+    # microwatt needs a stall signal (operates in pipeline mode)
+    if microwatt_compat or fabric_compat:
+        res.append(("stall", 1, DIR_FANIN))
+    if not cti:
+        return res
+    return res + [
+        ("cti",           3, DIR_FANOUT),
+        ("bte",           2, DIR_FANOUT),
+    ]
 
 
 class WishboneArbiter(Elaboratable):
-    def __init__(self):
-        self.bus = Record(wishbone_layout)
+    def __init__(self, pspec):
+        self.bus = Record(make_wb_layout(pspec))
         self._port_map = dict()
 
     def port(self, priority):
         if not isinstance(priority, int) or priority < 0:
-            raise TypeError("Priority must be a non-negative integer, not '{!r}'"
-                            .format(priority))
+            raise TypeError("Priority must be a non-negative "\
+                            "integer, not '{!r}'" .format(priority))
         if priority in self._port_map:
             raise ValueError("Conflicting priority: '{!r}'".format(priority))
         port = self._port_map[priority] = Record.like(self.bus)