|  | @@ -15,7 +15,7 @@
 | 
	
		
			
				|  |  |   *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 | 
	
		
			
				|  |  |   *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
	
		
			
				|  |  |   *
 | 
	
		
			
				|  |  | - *  Changes by hpa 2021:
 | 
	
		
			
				|  |  | + *  Changes by hpa 2021-2022:
 | 
	
		
			
				|  |  |   *  - maskirq instruction takes a mask in rs2.
 | 
	
		
			
				|  |  |   *  - retirq opcode changed to mret; no functional change.
 | 
	
		
			
				|  |  |   *  - qregs replaced with a full register bank switch. In general,
 | 
	
	
		
			
				|  | @@ -27,9 +27,11 @@
 | 
	
		
			
				|  |  |   *  - 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.
 | 
	
		
			
				|  |  | + *  - 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.
 | 
	
		
			
				|  |  | + *  - multiple user (non-interrupt) register banks (tasks) now supported;
 | 
	
		
			
				|  |  | + *
 | 
	
		
			
				|  |  |   */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /* verilator lint_off WIDTH */
 | 
	
	
		
			
				|  | @@ -92,60 +94,61 @@ module picorv32 #(
 | 
	
		
			
				|  |  |  	parameter [ 0:0] ENABLE_FAST_MUL = 0,
 | 
	
		
			
				|  |  |  	parameter [ 0:0] ENABLE_DIV = 0,
 | 
	
		
			
				|  |  |  	parameter [ 0:0] ENABLE_IRQ = 0,
 | 
	
		
			
				|  |  | -	parameter [ 0:0] ENABLE_IRQ_QREGS = 1,
 | 
	
		
			
				|  |  |  	parameter [ 0:0] ENABLE_IRQ_TIMER = 1,
 | 
	
		
			
				|  |  |  	parameter [ 0:0] ENABLE_TRACE = 0,
 | 
	
		
			
				|  |  |  	parameter [ 0:0] REGS_INIT_ZERO = 0,
 | 
	
		
			
				|  |  |  	parameter [31:0] MASKED_IRQ = 32'h 0000_0000,
 | 
	
		
			
				|  |  |  	parameter [31:0] LATCHED_IRQ = 32'h ffff_ffff,
 | 
	
		
			
				|  |  |  	parameter [31:0] STACKADDR = 32'h ffff_ffff,
 | 
	
		
			
				|  |  | -	parameter [ 4:0] RA_IRQ_REG   = ENABLE_IRQ_QREGS ? 26 : 3,
 | 
	
		
			
				|  |  | -	parameter [ 4:0] MASK_IRQ_REG = ENABLE_IRQ_QREGS ? 27 : 4
 | 
	
		
			
				|  |  | +	parameter [ 4:0] RA_IRQ_REG    = ENABLE_IRQ_QREGS ? 26 : 3,
 | 
	
		
			
				|  |  | +	parameter [ 4:0] MASK_IRQ_REG  = ENABLE_IRQ_QREGS ? 27 : 4,
 | 
	
		
			
				|  |  | +        parameter        USER_CONTEXTS = 1,
 | 
	
		
			
				|  |  | +	parameter [ 0:0] ENABLE_IRQ_QREGS = USER_CONTEXTS > 0
 | 
	
		
			
				|  |  |  ) (
 | 
	
		
			
				|  |  | -	input 		  clk, resetn,
 | 
	
		
			
				|  |  | -	input 		  halt,
 | 
	
		
			
				|  |  | -	output reg 	  trap,
 | 
	
		
			
				|  |  | +	input		  clk, resetn,
 | 
	
		
			
				|  |  | +	input		  halt,
 | 
	
		
			
				|  |  | +	output reg	  trap,
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	input [31:0] 	  progaddr_reset,
 | 
	
		
			
				|  |  | -        input [31:0] 	  progaddr_irq,
 | 
	
		
			
				|  |  | +	input [31:0]	  progaddr_reset,
 | 
	
		
			
				|  |  | +        input [31:0]	  progaddr_irq,
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	output reg 	  mem_valid,
 | 
	
		
			
				|  |  | -	output reg 	  mem_instr,
 | 
	
		
			
				|  |  | -	input 		  mem_ready,
 | 
	
		
			
				|  |  | +	output reg	  mem_valid,
 | 
	
		
			
				|  |  | +	output reg	  mem_instr,
 | 
	
		
			
				|  |  | +	input		  mem_ready,
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	output reg [31:0] mem_addr,
 | 
	
		
			
				|  |  |  	output reg [31:0] mem_wdata,
 | 
	
		
			
				|  |  |  	output reg [ 3:0] mem_wstrb,
 | 
	
		
			
				|  |  | -	input [31:0] 	  mem_rdata,
 | 
	
		
			
				|  |  | +	input [31:0]	  mem_rdata,
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	// Look-Ahead Interface
 | 
	
		
			
				|  |  | -	output 		  mem_la_read,
 | 
	
		
			
				|  |  | -	output 		  mem_la_write,
 | 
	
		
			
				|  |  | -	output [31:0] 	  mem_la_addr,
 | 
	
		
			
				|  |  | +	output		  mem_la_read,
 | 
	
		
			
				|  |  | +	output		  mem_la_write,
 | 
	
		
			
				|  |  | +	output [31:0]	  mem_la_addr,
 | 
	
		
			
				|  |  |  	output reg [31:0] mem_la_wdata,
 | 
	
		
			
				|  |  |  	output reg [ 3:0] mem_la_wstrb,
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	// Pico Co-Processor Interface (PCPI)
 | 
	
		
			
				|  |  | -	output reg 	  pcpi_valid,
 | 
	
		
			
				|  |  | +	output reg	  pcpi_valid,
 | 
	
		
			
				|  |  |  	output reg [31:0] pcpi_insn,
 | 
	
		
			
				|  |  | -	output [31:0] 	  pcpi_rs1,
 | 
	
		
			
				|  |  | -	output [31:0] 	  pcpi_rs2,
 | 
	
		
			
				|  |  | -	input 		  pcpi_wr,
 | 
	
		
			
				|  |  | -	input [31:0] 	  pcpi_rd,
 | 
	
		
			
				|  |  | -	input 		  pcpi_wait,
 | 
	
		
			
				|  |  | -	input 		  pcpi_ready,
 | 
	
		
			
				|  |  | +	output [31:0]	  pcpi_rs1,
 | 
	
		
			
				|  |  | +	output [31:0]	  pcpi_rs2,
 | 
	
		
			
				|  |  | +	input		  pcpi_wr,
 | 
	
		
			
				|  |  | +	input [31:0]	  pcpi_rd,
 | 
	
		
			
				|  |  | +	input		  pcpi_wait,
 | 
	
		
			
				|  |  | +	input		  pcpi_ready,
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	// IRQ Interface
 | 
	
		
			
				|  |  | -	input [31:0] 	  irq,
 | 
	
		
			
				|  |  | +	input [31:0]	  irq,
 | 
	
		
			
				|  |  |  	output reg [31:0] eoi,
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  `ifdef RISCV_FORMAL
 | 
	
		
			
				|  |  | -	output reg 	  rvfi_valid,
 | 
	
		
			
				|  |  | +	output reg	  rvfi_valid,
 | 
	
		
			
				|  |  |  	output reg [63:0] rvfi_order,
 | 
	
		
			
				|  |  |  	output reg [31:0] rvfi_insn,
 | 
	
		
			
				|  |  | -	output reg 	  rvfi_trap,
 | 
	
		
			
				|  |  | -	output reg 	  rvfi_halt,
 | 
	
		
			
				|  |  | -	output reg 	  rvfi_intr,
 | 
	
		
			
				|  |  | +	output reg	  rvfi_trap,
 | 
	
		
			
				|  |  | +	output reg	  rvfi_halt,
 | 
	
		
			
				|  |  | +	output reg	  rvfi_intr,
 | 
	
		
			
				|  |  |  	output reg [ 1:0] rvfi_mode,
 | 
	
		
			
				|  |  |  	output reg [ 1:0] rvfi_ixl,
 | 
	
		
			
				|  |  |  	output reg [ 4:0] rvfi_rs1_addr,
 | 
	
	
		
			
				|  | @@ -174,7 +177,7 @@ module picorv32 #(
 | 
	
		
			
				|  |  |  `endif
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	// Trace Interface
 | 
	
		
			
				|  |  | -	output reg 	  trace_valid,
 | 
	
		
			
				|  |  | +	output reg	  trace_valid,
 | 
	
		
			
				|  |  |  	output reg [35:0] trace_data
 | 
	
		
			
				|  |  |  );
 | 
	
		
			
				|  |  |  	localparam integer irq_timer = 0;
 | 
	
	
		
			
				|  | @@ -182,11 +185,18 @@ module picorv32 #(
 | 
	
		
			
				|  |  |  	localparam integer irq_buserror = 2;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	localparam integer xreg_count   = ENABLE_REGS_16_31 ? 32 : 16;
 | 
	
		
			
				|  |  | -        localparam integer qreg_count   = (ENABLE_IRQ && ENABLE_IRQ_QREGS) ? xreg_count : 0;
 | 
	
		
			
				|  |  | -        localparam integer qreg_offset  = qreg_count; // 0 for no qregs
 | 
	
		
			
				|  |  | -        localparam integer regfile_size = xreg_count + qreg_count;
 | 
	
		
			
				|  |  | -        localparam integer regindex_bits = $clog2(regfile_size);
 | 
	
		
			
				|  |  | -	wire [regindex_bits-1:0] xreg_mask = xreg_count - 1;
 | 
	
		
			
				|  |  | +        localparam integer xreg_bits    = $clog2(xreg_count);
 | 
	
		
			
				|  |  | +        localparam integer xreg_banks   = USER_CONTEXTS + 1;
 | 
	
		
			
				|  |  | +        localparam integer context_bits = $clog2(xreg_banks);
 | 
	
		
			
				|  |  | +        localparam integer regfile_size = xreg_count * xreg_banks;
 | 
	
		
			
				|  |  | +        localparam integer regfile_bits = $clog2(regfile_size);
 | 
	
		
			
				|  |  | +	wire [regfile_bits-1:0] xreg_mask = xreg_count - 1;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        reg [context_bits-1:0]	user_context;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        wire [regfile_bits-1:0]		xreg_offset;
 | 
	
		
			
				|  |  | +        assign xreg_offset[regfile_bits-1:xreg_bits] = irq_active ? 0 : user_context;
 | 
	
		
			
				|  |  | +	assign xreg_offset[xreg_bits-1:0] = 0;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	localparam WITH_PCPI = ENABLE_PCPI || ENABLE_MUL || ENABLE_FAST_MUL || ENABLE_DIV;
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -241,7 +251,7 @@ module picorv32 #(
 | 
	
		
			
				|  |  |  	endtask
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  `ifdef DEBUGREGS
 | 
	
		
			
				|  |  | -`define dr_reg(x) cpuregs[x | (irq_active ? qreg_offset : 0)]
 | 
	
		
			
				|  |  | +`define dr_reg(x) cpuregs[x | xreg_offset]
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	wire [31:0] dbg_reg_x0  = 0;
 | 
	
		
			
				|  |  |  	wire [31:0] dbg_reg_x1  = `dr_reg(1);
 | 
	
	
		
			
				|  | @@ -675,10 +685,11 @@ module picorv32 #(
 | 
	
		
			
				|  |  |  	reg instr_add, instr_sub, instr_sll, instr_slt, instr_sltu, instr_xor, instr_srl, instr_sra, instr_or, instr_and;
 | 
	
		
			
				|  |  |  	reg instr_csrr, instr_ecall_ebreak;
 | 
	
		
			
				|  |  |  	reg instr_addqxi, instr_addxqi, instr_retirq, instr_maskirq, instr_waitirq, instr_timer;
 | 
	
		
			
				|  |  | +        reg [2:0] instr_funct2;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	wire instr_trap;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	reg [regindex_bits-1:0] decoded_rd, decoded_rs1, decoded_rs2;
 | 
	
		
			
				|  |  | +	reg [regfile_bits-1:0] decoded_rd, decoded_rs1, decoded_rs2;
 | 
	
		
			
				|  |  |  	reg [31:0] decoded_imm, decoded_imm_j;
 | 
	
		
			
				|  |  |  	reg decoder_trigger;
 | 
	
		
			
				|  |  |  	reg decoder_trigger_q;
 | 
	
	
		
			
				|  | @@ -1057,16 +1068,16 @@ module picorv32 #(
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  		        if (ENABLE_IRQ && ENABLE_IRQ_QREGS)
 | 
	
		
			
				|  |  |  			  begin
 | 
	
		
			
				|  |  | -			     decoded_rd [regindex_bits-1] <= irq_active;
 | 
	
		
			
				|  |  | -			     decoded_rs1[regindex_bits-1] <= irq_active;
 | 
	
		
			
				|  |  | -			     decoded_rs2[regindex_bits-1] <= irq_active;
 | 
	
		
			
				|  |  | +			     decoded_rd [regfile_bits-1:xreg_bits] <= irq_active ? 0 : user_context;
 | 
	
		
			
				|  |  | +			     decoded_rs1[regfile_bits-1:xreg_bits] <= irq_active ? 0 : user_context;
 | 
	
		
			
				|  |  | +			     decoded_rs2[regfile_bits-1:xreg_bits] <= irq_active ? 0 : user_context;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  			     // addqxi, addxqi
 | 
	
		
			
				|  |  |  			     if (mem_rdata_latched[6:0] == 7'b0001011 && mem_rdata_latched[14:13] == 2'b01) begin
 | 
	
		
			
				|  |  |  				is_addqxi <= 1; // True for both addqxi and addxqi
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -				decoded_rd [regindex_bits-1] <= ~mem_rdata_latched[12]; // addxqi
 | 
	
		
			
				|  |  | -				decoded_rs1[regindex_bits-1] <=  mem_rdata_latched[12]; // addqxi
 | 
	
		
			
				|  |  | +				decoded_rd [regfile_bits-1:xreg_bits] <= ~mem_rdata_latched[12] ? 0 : user_context;
 | 
	
		
			
				|  |  | +				decoded_rs1[regfile_bits-1:xreg_bits] <=  mem_rdata_latched[12] ? 0 : user_context;
 | 
	
		
			
				|  |  |  			     end
 | 
	
		
			
				|  |  |  			  end
 | 
	
		
			
				|  |  |  		end // if (mem_do_rinst && mem_done)
 | 
	
	
		
			
				|  | @@ -1113,10 +1124,9 @@ module picorv32 #(
 | 
	
		
			
				|  |  |  			instr_or    <= is_alu_reg_reg && mem_rdata_q[14:12] == 3'b110 && mem_rdata_q[31:25] == 7'b0000000;
 | 
	
		
			
				|  |  |  			instr_and   <= is_alu_reg_reg && mem_rdata_q[14:12] == 3'b111 && mem_rdata_q[31:25] == 7'b0000000;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -			// The only CSR reference supported is CSRR
 | 
	
		
			
				|  |  | -			instr_csrr     <= (mem_rdata_q[6:0] == 7'b1110011 && mem_rdata_q[19:12] == 'b00000010);
 | 
	
		
			
				|  |  | +		        instr_csrr     <= (mem_rdata_q[6:0] == 7'b1110011 && mem_rdata_q[13:12] != 2'b00);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -			instr_ecall_ebreak <= ((mem_rdata_q[6:0] == 7'b1110011 && !mem_rdata_q[31:21] && !mem_rdata_q[19:7]) ||
 | 
	
		
			
				|  |  | +			instr_ecall_ebreak <= ((mem_rdata_q[6:0] == 7'b1110011 && !mem_rdata_q[13:12]) ||
 | 
	
		
			
				|  |  |  					(COMPRESSED_ISA && mem_rdata_q[15:0] == 16'h9002));
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  			instr_maskirq <= mem_rdata_q[6:0] == 7'b0001011 && mem_rdata_q[14:12] == 3'b000 && mem_rdata_q[31:25] == 7'b0000011 && ENABLE_IRQ;
 | 
	
	
		
			
				|  | @@ -1163,7 +1173,9 @@ module picorv32 #(
 | 
	
		
			
				|  |  |  					decoded_imm <= $signed({mem_rdata_q[31:25], mem_rdata_q[11:7]});
 | 
	
		
			
				|  |  |  				default:
 | 
	
		
			
				|  |  |  					decoded_imm <= $signed(mem_rdata_q[31:20]);
 | 
	
		
			
				|  |  | -			endcase
 | 
	
		
			
				|  |  | +			endcase // case (1'b1)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		        instr_funct2 <= mem_rdata_q[14:12];
 | 
	
		
			
				|  |  |  		end
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  		if (!resetn) begin
 | 
	
	
		
			
				|  | @@ -1239,7 +1251,7 @@ module picorv32 #(
 | 
	
		
			
				|  |  |  	reg latched_is_lu;
 | 
	
		
			
				|  |  |  	reg latched_is_lh;
 | 
	
		
			
				|  |  |  	reg latched_is_lb;
 | 
	
		
			
				|  |  | -	reg [regindex_bits-1:0] latched_rd;
 | 
	
		
			
				|  |  | +	reg [regfile_bits-1:0] latched_rd;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	reg [31:0] current_pc;
 | 
	
		
			
				|  |  |  	assign next_pc = latched_store && latched_branch ? reg_out & ~1 : reg_next_pc;
 | 
	
	
		
			
				|  | @@ -1336,7 +1348,7 @@ module picorv32 #(
 | 
	
		
			
				|  |  |  	reg [31:0] cpuregs_wrdata;
 | 
	
		
			
				|  |  |  	reg [31:0] cpuregs_rs1;
 | 
	
		
			
				|  |  |  	reg [31:0] cpuregs_rs2;
 | 
	
		
			
				|  |  | -	reg [regindex_bits-1:0] decoded_rs;
 | 
	
		
			
				|  |  | +	reg [regfile_bits-1:0] decoded_rs;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	always @* begin
 | 
	
		
			
				|  |  |  		cpuregs_write = 0;
 | 
	
	
		
			
				|  | @@ -1411,9 +1423,9 @@ module picorv32 #(
 | 
	
		
			
				|  |  |  	wire[31:0] cpuregs_rdata1;
 | 
	
		
			
				|  |  |  	wire[31:0] cpuregs_rdata2;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	wire [5:0] cpuregs_waddr = latched_rd;
 | 
	
		
			
				|  |  | -	wire [5:0] cpuregs_raddr1 = ENABLE_REGS_DUALPORT ? decoded_rs1 : decoded_rs;
 | 
	
		
			
				|  |  | -	wire [5:0] cpuregs_raddr2 = ENABLE_REGS_DUALPORT ? decoded_rs2 : 0;
 | 
	
		
			
				|  |  | +	wire [regfile_bits-1:0] cpuregs_waddr = latched_rd;
 | 
	
		
			
				|  |  | +	wire [regfile_bits-1:0] cpuregs_raddr1 = ENABLE_REGS_DUALPORT ? decoded_rs1 : decoded_rs;
 | 
	
		
			
				|  |  | +	wire [regfile_bits-1:0] cpuregs_raddr2 = ENABLE_REGS_DUALPORT ? decoded_rs2 : 0;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	`PICORV32_REGS cpuregs (
 | 
	
		
			
				|  |  |  		.clk(clk),
 | 
	
	
		
			
				|  | @@ -1443,6 +1455,8 @@ module picorv32 #(
 | 
	
		
			
				|  |  |  				  decoder_trigger &&
 | 
	
		
			
				|  |  |  				  (!ENABLE_IRQ || irq_delay || irq_active || !(irq_pending & ~irq_mask));
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +        wire [31:0] csrr_src = instr_funct2[2] ? { 29'b0, decoded_rs1[4:0] } : cpuregs_rs1;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  	always @(posedge clk) begin
 | 
	
		
			
				|  |  |  		trap <= 0;
 | 
	
		
			
				|  |  |  		reg_sh <= 'bx;
 | 
	
	
		
			
				|  | @@ -1510,6 +1524,7 @@ module picorv32 #(
 | 
	
		
			
				|  |  |  			latched_is_lu <= 0;
 | 
	
		
			
				|  |  |  			latched_is_lh <= 0;
 | 
	
		
			
				|  |  |  			latched_is_lb <= 0;
 | 
	
		
			
				|  |  | +		        user_context <= USER_CONTEXTS; // On reset highest supported context
 | 
	
		
			
				|  |  |  			pcpi_valid <= 0;
 | 
	
		
			
				|  |  |  			pcpi_timeout <= 0;
 | 
	
		
			
				|  |  |  			irq_active <= 0;
 | 
	
	
		
			
				|  | @@ -1521,7 +1536,7 @@ module picorv32 #(
 | 
	
		
			
				|  |  |  			timer <= 0;
 | 
	
		
			
				|  |  |  			if (~STACKADDR) begin
 | 
	
		
			
				|  |  |  				latched_store <= 1;
 | 
	
		
			
				|  |  | -				latched_rd <= 2;
 | 
	
		
			
				|  |  | +				latched_rd <= (USER_CONTEXTS << xreg_bits) | 2;
 | 
	
		
			
				|  |  |  				reg_out <= STACKADDR;
 | 
	
		
			
				|  |  |  			end
 | 
	
		
			
				|  |  |  			cpu_state <= cpu_state_fetch;
 | 
	
	
		
			
				|  | @@ -1587,8 +1602,7 @@ module picorv32 #(
 | 
	
		
			
				|  |  |  						irq_state == 2'b00 ? 2'b01 :
 | 
	
		
			
				|  |  |  						irq_state == 2'b01 ? 2'b10 : 2'b00;
 | 
	
		
			
				|  |  |  					latched_compr <= latched_compr;
 | 
	
		
			
				|  |  | -				        latched_rd <= qreg_offset |
 | 
	
		
			
				|  |  | -						      (irq_state[0] ? MASK_IRQ_REG : RA_IRQ_REG);
 | 
	
		
			
				|  |  | +				        latched_rd <= irq_state[0] ? MASK_IRQ_REG : RA_IRQ_REG;
 | 
	
		
			
				|  |  |  				end else
 | 
	
		
			
				|  |  |  				if (ENABLE_IRQ && do_waitirq) begin
 | 
	
		
			
				|  |  |  					if (&(irq_pending | ~reg_op1) || |(irq_pending & reg_op2)) begin
 | 
	
	
		
			
				|  | @@ -1675,6 +1689,7 @@ module picorv32 #(
 | 
	
		
			
				|  |  |  						end
 | 
	
		
			
				|  |  |  					end
 | 
	
		
			
				|  |  |  					instr_csrr: begin
 | 
	
		
			
				|  |  | +						// Always read (suppress iff rd == 0 and side effects)
 | 
	
		
			
				|  |  |  						reg_out <= 32'bx;
 | 
	
		
			
				|  |  |  						case (decoded_imm[11:0])
 | 
	
		
			
				|  |  |  							12'hc00, 12'hc01:	 // cycle, time
 | 
	
	
		
			
				|  | @@ -1687,9 +1702,24 @@ module picorv32 #(
 | 
	
		
			
				|  |  |  							  if (ENABLE_COUNTERS64) reg_out <= count_instr[63:32];
 | 
	
		
			
				|  |  |  							12'h343:		 // mtval
 | 
	
		
			
				|  |  |  							  if (CATCH_MISALIGN)    reg_out <= buserr_address;
 | 
	
		
			
				|  |  | +						        12'h7f0:                 // user_context
 | 
	
		
			
				|  |  | +							  if (USER_CONTEXTS > 0) reg_out <= user_context;
 | 
	
		
			
				|  |  |  							default:
 | 
	
		
			
				|  |  |  							  reg_out <= 32'bx;
 | 
	
		
			
				|  |  |  						endcase // case (decoded_imm[11:0])
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +					        // Bitops not supported ATM, treat as readonly
 | 
	
		
			
				|  |  | +					        if (~instr_funct2[1])
 | 
	
		
			
				|  |  | +						  case (decoded_imm[11:0])
 | 
	
		
			
				|  |  | +						    12'h7f0: begin			// user_context
 | 
	
		
			
				|  |  | +						       user_context <= csrr_src;
 | 
	
		
			
				|  |  | +						       irq_active   <= 1'b1;
 | 
	
		
			
				|  |  | +						    end
 | 
	
		
			
				|  |  | +						    default: begin
 | 
	
		
			
				|  |  | +						       // Do nothing
 | 
	
		
			
				|  |  | +						    end
 | 
	
		
			
				|  |  | +						  endcase // case (decoded_imm[11:0])
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  						latched_store <= 1;
 | 
	
		
			
				|  |  |  						cpu_state <= cpu_state_fetch;
 | 
	
		
			
				|  |  |  					end
 |