whoops forgot to make CU decisions based on latched opcode
[soc.git] / src / experiment / compalu.py
index 06cd9e5763b05767fe4b11d3075ca918f70c90d8..1735e24cf09e6fc2a273fcf139b0feed99f6e101 100644 (file)
@@ -18,7 +18,7 @@ from nmutil.latch import SRLatch, latchregister
       The src1 and src2 registers and the operand can be latched in
       at this point
 
-    * Read request is set, which is ackowledged through the Scoreboard
+    * Read request is set, which is acknowledged through the Scoreboard
       to the priority picker, which generates (one and only one) Go_Read
       at a time.  One of those will (eventually) be this Computation Unit.
 
@@ -47,8 +47,11 @@ class ComputationUnitNoDelay(Elaboratable):
         self.go_rd_i = Signal(reset_less=True) # go read in
         self.go_wr_i = Signal(reset_less=True) # go write in
         self.issue_i = Signal(reset_less=True) # fn issue in
+        self.shadown_i = Signal(reset=1) # shadow function, defaults to ON
+        self.go_die_i = Signal() # go die (reset)
 
         self.oper_i = Signal(opwid, reset_less=True) # opcode in
+        self.imm_i = Signal(rwid, reset_less=True) # immediate in
         self.src1_i = Signal(rwid, reset_less=True) # oper1 in
         self.src2_i = Signal(rwid, reset_less=True) # oper2 in
 
@@ -64,43 +67,55 @@ class ComputationUnitNoDelay(Elaboratable):
         m.submodules.opc_l = opc_l = SRLatch(sync=False)
         m.submodules.req_l = req_l = SRLatch(sync=False)
 
+        # shadow/go_die
+        reset_w = Signal(reset_less=True)
+        reset_r = Signal(reset_less=True)
+        m.d.comb += reset_w.eq(self.go_wr_i | self.go_die_i)
+        m.d.comb += reset_r.eq(self.go_rd_i | self.go_die_i)
+
         # This is fascinating and very important to observe that this
         # is in effect a "3-way revolving door".  At no time may all 3
         # latches be set at the same time.
 
         # opcode latch (not using go_rd_i) - inverted so that busy resets to 0
         m.d.sync += opc_l.s.eq(self.issue_i) # XXX NOTE: INVERTED FROM book!
-        m.d.sync += opc_l.r.eq(self.go_wr_i) # XXX NOTE: INVERTED FROM book!
+        m.d.sync += opc_l.r.eq(reset_w)      # XXX NOTE: INVERTED FROM book!
 
         # src operand latch (not using go_wr_i)
         m.d.sync += src_l.s.eq(self.issue_i)
-        m.d.sync += src_l.r.eq(self.go_rd_i)
+        m.d.sync += src_l.r.eq(reset_r)
 
         # dest operand latch (not using issue_i)
         m.d.sync += req_l.s.eq(self.go_rd_i)
-        m.d.sync += req_l.r.eq(self.go_wr_i)
+        m.d.sync += req_l.r.eq(reset_w)
 
         # XXX
         # XXX NOTE: sync on req_rel_o and data_o due to simulation lock-up
         # XXX
 
         # outputs
-        m.d.comb += self.busy_o.eq(opc_l.q) # busy out
-        m.d.comb += self.rd_rel_o.eq(src_l.q & opc_l.q) # src1/src2 req rel
+        busy_o = self.busy_o
+        m.d.comb += busy_o.eq(opc_l.q) # busy out
+        m.d.comb += self.rd_rel_o.eq(src_l.q & busy_o) # src1/src2 req rel
 
+        # the counter is just for demo purposes, to get the ALUs of different
+        # types to take arbitrary completion times
         with m.If(opc_l.qn):
             m.d.sync += self.counter.eq(0)
-        with m.If(req_l.qn & opc_l.q & (self.counter == 0)):
-            with m.If(self.oper_i == 2): # MUL, to take 5 instructions
+        with m.If(req_l.qn & busy_o & (self.counter == 0)):
+            with m.If(self.alu.op == 2): # MUL, to take 5 instructions
                 m.d.sync += self.counter.eq(5)
-            with m.Elif(self.oper_i == 3): # SHIFT to take 7
+            with m.Elif(self.alu.op == 3): # SHIFT to take 7
                 m.d.sync += self.counter.eq(7)
+            with m.Elif(self.alu.op >= 4): # Branches take 6 (to test shadow)
+                m.d.sync += self.counter.eq(6)
             with m.Else(): # ADD/SUB to take 2
                 m.d.sync += self.counter.eq(2)
         with m.If(self.counter > 1):
             m.d.sync += self.counter.eq(self.counter - 1)
         with m.If(self.counter == 1):
-            m.d.comb += self.req_rel_o.eq(req_l.q & opc_l.q) # req release out
+            # write req release out.  waits until shadow is dropped.
+            m.d.comb += self.req_rel_o.eq(req_l.q & busy_o & self.shadown_i)
 
         # create a latch/register for src1/src2
         latchregister(m, self.src1_i, self.alu.a, src_l.q)
@@ -109,7 +124,7 @@ class ComputationUnitNoDelay(Elaboratable):
         #    m.d.comb += self.alu.op.eq(self.oper_i)
 
         # create a latch/register for the operand
-        latchregister(m, self.oper_i, self.alu.op, src_l.q)
+        latchregister(m, self.oper_i, self.alu.op, self.issue_i)
 
         # and one for the output from the ALU
         data_r = Signal(self.rwid, reset_less=True) # Dest register