add detection and disable of Instruction Wishbone based on JTAG command
[soc.git] / src / soc / minerva / units / fetch.py
index 74d6d8e6e002de66e8e15e780c317c054981d554..a1f14b3d5dfbeafcee830b86a0fc4192920b0b41 100644 (file)
@@ -12,8 +12,11 @@ class FetchUnitInterface:
     def __init__(self, pspec):
         self.pspec = pspec
         self.addr_wid = pspec.addr_wid
-        self.data_wid = pspec.reg_wid
-        self.adr_lsbs = log2_int(pspec.reg_wid//8)
+        if isinstance(pspec.imem_reg_wid, int):
+            self.data_wid = pspec.imem_reg_wid
+        else:
+            self.data_wid = pspec.reg_wid
+        self.adr_lsbs = log2_int(self.data_wid//8)
         self.ibus = Record(make_wb_layout(pspec))
         bad_wid = pspec.addr_wid - self.adr_lsbs # TODO: is this correct?
 
@@ -31,6 +34,14 @@ class FetchUnitInterface:
         self.f_fetch_err_o = Signal()
         self.f_badaddr_o = Signal(bad_wid)
 
+        # detect whether the wishbone bus is enabled / disabled
+        if (hasattr(pspec, "wb_icache_en") and
+                     isinstance(pspec.wb_icache_en, Signal)):
+            self.jtag_en = pspec.wb_icache_en
+        else:
+            self.jtag_en = Const(1, 1) # permanently on
+
+
     def __iter__(self):
         yield self.a_pc_i
         yield self.a_stall_i
@@ -53,38 +64,42 @@ class BareFetchUnit(FetchUnitInterface, Elaboratable):
     def elaborate(self, platform):
         m = Module()
 
-        ibus_rdata = Signal.like(self.ibus.dat_r)
-        with m.If(self.ibus.cyc):
-            with m.If(self.ibus.ack | self.ibus.err | ~self.f_valid_i):
+        with m.If(self.jtag_en): # for safety, JTAG can completely disable WB
+
+            ibus_rdata = Signal.like(self.ibus.dat_r)
+            with m.If(self.ibus.cyc):
+                with m.If(self.ibus.ack | self.ibus.err | ~self.f_valid_i):
+                    m.d.sync += [
+                        self.ibus.cyc.eq(0),
+                        self.ibus.stb.eq(0),
+                        self.ibus.sel.eq(0),
+                        ibus_rdata.eq(self.ibus.dat_r)
+                    ]
+            with m.Elif(self.a_valid_i & ~self.a_stall_i):
                 m.d.sync += [
-                    self.ibus.cyc.eq(0),
-                    self.ibus.stb.eq(0),
-                    ibus_rdata.eq(self.ibus.dat_r)
+                    self.ibus.adr.eq(self.a_pc_i[self.adr_lsbs:]),
+                    self.ibus.cyc.eq(1),
+                    self.ibus.stb.eq(1),
+                    self.ibus.sel.eq((1<<(1<<self.adr_lsbs))-1),
                 ]
-        with m.Elif(self.a_valid_i & ~self.a_stall_i):
-            m.d.sync += [
-                self.ibus.adr.eq(self.a_pc_i[self.adr_lsbs:]),
-                self.ibus.cyc.eq(1),
-                self.ibus.stb.eq(1)
-            ]
 
-        with m.If(self.ibus.cyc & self.ibus.err):
-            m.d.sync += [
-                self.f_fetch_err_o.eq(1),
-                self.f_badaddr_o.eq(self.ibus.adr)
-            ]
-        with m.Elif(~self.f_stall_i):
-            m.d.sync += self.f_fetch_err_o.eq(0)
+            with m.If(self.ibus.cyc & self.ibus.err):
+                m.d.sync += [
+                    self.f_fetch_err_o.eq(1),
+                    self.f_badaddr_o.eq(self.ibus.adr)
+                ]
+            with m.Elif(~self.f_stall_i):
+                m.d.sync += self.f_fetch_err_o.eq(0)
 
-        m.d.comb += self.a_busy_o.eq(self.ibus.cyc)
+            m.d.comb += self.a_busy_o.eq(self.ibus.cyc)
 
-        with m.If(self.f_fetch_err_o):
-            m.d.comb += self.f_busy_o.eq(0)
-        with m.Else():
-            m.d.comb += [
-                self.f_busy_o.eq(self.ibus.cyc),
-                self.f_instr_o.eq(ibus_rdata)
-            ]
+            with m.If(self.f_fetch_err_o):
+                m.d.comb += self.f_busy_o.eq(0)
+            with m.Else():
+                m.d.comb += [
+                    self.f_busy_o.eq(self.ibus.cyc),
+                    self.f_instr_o.eq(ibus_rdata)
+                ]
 
         return m
 
@@ -169,12 +184,14 @@ class CachedFetchUnit(FetchUnitInterface, Elaboratable):
                 m.d.sync += [
                     bare_port.cyc.eq(0),
                     bare_port.stb.eq(0),
+                    bare_port.sel.eq(0),
                     bare_rdata.eq(bare_port.dat_r)
                 ]
         with m.Elif(~a_icache_select & self.a_valid_i & ~self.a_stall_i):
             m.d.sync += [
                 bare_port.cyc.eq(1),
                 bare_port.stb.eq(1),
+                bare_port.sel.eq((1<<(1<<self.adr_lsbs))-1),
                 bare_port.adr.eq(self.a_pc_i[self.adr_lsbs:])
             ]