add LDSTException to PortInterface
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Tue, 6 Oct 2020 13:03:53 +0000 (14:03 +0100)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Tue, 6 Oct 2020 13:03:53 +0000 (14:03 +0100)
src/soc/experiment/compldst_multi.py
src/soc/experiment/pi2ls.py
src/soc/experiment/pimem.py

index 9f64b4fa18abd10580c7a1f60c7a0a5f90fdc02a..8e9f4ec35718541824a78e3ab857dfbf8f307378 100644 (file)
@@ -89,6 +89,7 @@ from nmutil.extend import exts
 
 from soc.experiment.compalu_multi import go_record, CompUnitRecord
 from soc.experiment.l0_cache import PortInterface
+from soc.experiment.pimem import LDSTException
 from soc.fu.regspec import RegSpecAPI
 
 from soc.decoder.power_enums import MicrOp, Function, LDSTMode
@@ -104,7 +105,7 @@ class LDSTCompUnitRecord(CompUnitRecord):
         self.ad = go_record(1, name="cu_ad")  # address go in, req out
         self.st = go_record(1, name="cu_st")  # store go in, req out
 
-        self.addr_exc_o = Signal(reset_less=True)   # address exception
+        self.exception_o = LDSTException("exc")
 
         self.ld_o = Signal(reset_less=True)  # operation is a LD
         self.st_o = Signal(reset_less=True)  # operation is a ST
@@ -132,9 +133,9 @@ class LDSTCompUnit(RegSpecAPI, Elaboratable):
     --------------
     * :data_o:     Dest out (LD)          - managed by wr[0] go/req
     * :addr_o:     Address out (LD or ST) - managed by wr[1] go/req
-    * :addr_exc_o: Address/Data Exception occurred.  LD/ST must terminate
+    * :exception_o: Address/Data Exception occurred.  LD/ST must terminate
 
-    TODO: make addr_exc_o a data-type rather than a single-bit signal
+    TODO: make exception_o a data-type rather than a single-bit signal
           (see bug #302)
 
     Control Signals (In)
@@ -227,7 +228,7 @@ class LDSTCompUnit(RegSpecAPI, Elaboratable):
 
         self.data_o = Data(self.data_wid, name="o")  # Dest1 out: RT
         self.addr_o = Data(self.data_wid, name="ea")  # Addr out: Update => RA
-        self.addr_exc_o = cu.addr_exc_o
+        self.exception_o = cu.exception_o
         self.done_o = cu.done_o
         self.busy_o = cu.busy_o
 
@@ -491,7 +492,7 @@ class LDSTCompUnit(RegSpecAPI, Elaboratable):
         # address: use sync to avoid long latency
         sync += pi.addr.data.eq(addr_r)           # EA from adder
         sync += pi.addr.ok.eq(alu_ok & lsd_l.q)  # "do address stuff" (once)
-        comb += self.addr_exc_o.eq(pi.addr_exc_o)  # exception occurred
+        comb += self.exception_o.eq(pi.exception_o)  # exception occurred
         comb += addr_ok.eq(self.pi.addr_ok_o)  # no exc, address fine
 
         # byte-reverse on LD
index 3964122b3ca21cc9bfa9c4d50487de69edec1b11..abba37e1a80721e4dd410e33f6fa9a4b7b899ef0 100644 (file)
@@ -14,7 +14,7 @@
     addr.ok/1       probably x_valid_i & ~x_stall_i
 
     addr_ok_o/1     no equivalent.  *might* work using x_stall_i
-    addr_exc_o/2(?) m_load_err_o and m_store_err_o
+    exception_o/2(?) m_load_err_o and m_store_err_o
 
     ld.data/64      m_ld_data_o
     ld.ok/1         probably implicit, when x_busy drops low
index 89ba7714dc85a0d816d2e338a1cfffc18b4520ab..dc846c127aca528038e164dd0549a79c7979522a 100644 (file)
@@ -33,6 +33,18 @@ from soc.experiment.testmem import TestMemory
 
 import unittest
 
+class LDSTException(RecordObject):
+    def __init__(self, name=None):
+        RecordObject.__init__(self, name=name)
+        self.happened = Signal()
+        self.alignment = Signal()
+        self.instr_fault = Signal()
+        self.invalid = Signal()
+        self.badtree = Signal()
+        self.perm_error = Signal()
+        self.rc_error = Signal()
+        self.segment_fault = Signal()
+
 
 class PortInterface(RecordObject):
     """PortInterface
@@ -59,13 +71,13 @@ class PortInterface(RecordObject):
       for the L0 Cache/Buffer to have an additional address latch
       (because the LDSTCompUnit already has it)
 
-    * addr_ok_o (or addr_exc_o) must be waited for.  these will
+    * addr_ok_o (or exception.happened) must be waited for.  these will
       be asserted *only* for one cycle and one cycle only.
 
-    * addr_exc_o will be asserted if there is no chance that the
+    * exception.happened will be asserted if there is no chance that the
       memory request may be fulfilled.
 
-      busy_o is deasserted on the same cycle as addr_exc_o is asserted.
+      busy_o is deasserted on the same cycle as exception.happened is asserted.
 
     * conversely: addr_ok_o must *ONLY* be asserted if there is a
       HUNDRED PERCENT guarantee that the memory request will be
@@ -107,7 +119,7 @@ class PortInterface(RecordObject):
         self.addr = Data(addrwid, "addr_i")            # addr/addr-ok
         # addr is valid (TLB, L1 etc.)
         self.addr_ok_o = Signal(reset_less=True)
-        self.addr_exc_o = Signal(reset_less=True)  # TODO, "type" of exception
+        self.exception_o = LDSTException("exc")
 
         # LD/ST
         self.ld = Data(regwid, "ld_data_o")  # ok to be set by L0 Cache/Buf
@@ -131,7 +143,7 @@ class PortInterface(RecordObject):
                 inport.ld.eq(self.ld),
                 inport.busy_o.eq(self.busy_o),
                 inport.addr_ok_o.eq(self.addr_ok_o),
-                inport.addr_exc_o.eq(self.addr_exc_o),
+                inport.exception_o.eq(self.exception_o),
                 ]
 
 
@@ -280,7 +292,7 @@ class PortInterfaceBase(Elaboratable):
             comb += st_done.r.eq(1)     # store done reset
 
         # monitor for an exception or the completion of LD.
-        with m.If(self.pi.addr_exc_o):
+        with m.If(self.pi.exception_o.happened):
             comb += busy_l.r.eq(1)
 
         # however ST needs one cycle before busy is reset