Browse Source

Add to waitirq and "andmask" and an "ormask".

Add an "andmask" and an "ormask" to waitirq. This can be used to wait
for a specific event, i.e. a device becoming available, without
enabling an interrupt.
H. Peter Anvin 3 years ago
parent
commit
affd869f20
2 changed files with 16 additions and 10 deletions
  1. 4 1
      fpga/picorv32.v
  2. 12 9
      fw/picorv32.h

+ 4 - 1
fpga/picorv32.v

@@ -27,6 +27,9 @@
  *  - PROGADDR_RESET and PROGADDR_IRQ changed to ports (allows external
  *    implementation of vectorized interrupts or fallback reset.)
  *  - maskirq, waitirq and timer require func3 == 3'b000.
+ * -  add two masks to waitirq: an AND mask and an OR mask.
+ *    waitirq exists if either all interrupts in the AND
+ *    mask are pending or any interrupt in the OR mask is pending.
  */
 
 /* verilator lint_off WIDTH */
@@ -1592,7 +1595,7 @@ module picorv32 #(
 						      (irq_state[0] ? MASK_IRQ_REG : RA_IRQ_REG);
 				end else
 				if (ENABLE_IRQ && (decoder_trigger || do_waitirq) && instr_waitirq) begin
-					if (irq_pending) begin
+					if (&(irq_pending | ~cpuregs_rs1) | |(irq_pending & cpuregs_rs2)) begin
 						latched_store <= 1;
 						reg_out <= irq_pending;
 						reg_next_pc <= current_pc + (compressed_instr ? 2 : 4);

+ 12 - 9
fw/picorv32.h

@@ -22,25 +22,28 @@ static inline unsigned int
 p_maskirq(unsigned int newmask, unsigned int keepmask)
 {
     unsigned int oldmask;
-    asm volatile(".insn r 0x0b, 0, 3, %0, %1, %2"
+    asm volatile(".insn r 0x0b, 0, 3, %0, %z1, %z2"
 		 : "=r" (oldmask)
-		 : "r" (newmask), "r" (keepmask));
+		 : "Jr" (newmask), "Jr" (keepmask));
     return oldmask;
 }
 
-static inline unsigned int p_waitirq(void)
+static inline unsigned int
+p_waitirq(unsigned int andmask, unsigned int ormask)
 {
     unsigned int pending_mask;
-    asm volatile(".insn r 0x0b, 0, 4, %0, zero, zero"
-		 : "=r" (pending_mask));
+    asm volatile(".insn r 0x0b, 0, 4, %0, %z1, %z2"
+		 : "=r" (pending_mask)
+		 : "Jr" (andmask), "Jr" (ormask));
     return pending_mask;
 }
 
 static inline unsigned int p_timer(unsigned int newval)
 {
     unsigned int oldval;
-    asm volatile(".insn 0x0b, 0, 5, %0, %1, zero"
-		 : "=r" (oldval) : "r" (newval));
+    asm volatile(".insn 0x0b, 0, 5, %0, %z1, %z2"
+		 : "=r" (oldval)
+		 : "Jr" (newval), "Jr" (0));
 }
 
 #else  /* __ASSEMBLY__ */
@@ -64,8 +67,8 @@ static inline unsigned int p_timer(unsigned int newval)
 	.insn r 0x0b, 0, 3, \rd, \rs1, \rs2
 .endm
 
-.macro waitirq rd
-	.insn r 0x0b, 0, 4, \rd, zero, zero
+.macro waitirq rd, andmask, ormask
+	.insn r 0x0b, 0, 4, \rd, \andmask, \ormask
 .endm
 
 .macro timer rd, rs