X-Git-Url: https://git.libre-soc.org/?p=shakti-peripherals.git;a=blobdiff_plain;f=src%2Fperipherals%2Fplic%2Fplic.bsv;h=1f1661acb35b5951542a93d92bbb216987ec7d68;hp=0e94ee7bd7d075f37033ebdf68522a047d775ee1;hb=df9621ad270f10a2f59262cb5d6c5898fd50bbf4;hpb=6d4e16aebe4a95443fa12972695d86c16096ed6b diff --git a/src/peripherals/plic/plic.bsv b/src/peripherals/plic/plic.bsv index 0e94ee7..1f1661a 100644 --- a/src/peripherals/plic/plic.bsv +++ b/src/peripherals/plic/plic.bsv @@ -13,14 +13,17 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND */ package plic; import Vector::*; - //import defined_parameters::*; import defined_types::*; import ConfigReg::*; import Semi_FIFOF::*; import AXI4_Lite_Types::*; import BUtils ::*; import ConcatReg ::*; + import encoder ::*; `include "instance_defines.bsv" + +`define INTERRUPT_LEVELS 8 + // import ConfigReg::*; /*Platform level interrupt controller: Refer to RISC-V privilege spec-v-1.10 chapter 7 @@ -51,7 +54,8 @@ package plic; */ -interface Ifc_PLIC#(numeric type addr_width,numeric type word_size,numeric type no_of_ir_pins); +interface Ifc_PLIC#(numeric type addr_width,numeric type word_size,numeric type no_of_ir_pins, + numeric type no_of_ir_levels); interface Vector#(no_of_ir_pins,Ifc_global_interrupt) ifc_external_irq; interface Ifc_program_registers#(addr_width,word_size) ifc_prog_reg; method ActionValue#(Tuple2#(Bool,Bool)) intrpt_note; @@ -59,95 +63,36 @@ interface Ifc_PLIC#(numeric type addr_width,numeric type word_size,numeric type endinterface //(*conflict_free = "rl_prioritise, prog_reg"*) -module mkplic(Ifc_PLIC#(addr_width,word_size,no_of_ir_pins)) +module mkplic(Ifc_PLIC#(addr_width,word_size,no_of_ir_pins,no_of_ir_levels)) provisos( - Log#(no_of_ir_pins, priority_bits), + Log#(no_of_ir_pins, ir_bits), + Log#(no_of_ir_levels, priority_bits), Mul#(8,word_size,data_width), - Add#(1,priority_bits,x_priority_bits), - Add#(msb_priority,1,priority_bits), - Add#(msb_priority_bits,1,no_of_ir_pins), - Add#(b__, no_of_ir_pins, data_width), - Add#(c__, priority_bits, data_width), - Add#(a__, 8, no_of_ir_pins), - Add#(e__, 32, data_width), - Add#(g__, 32, no_of_ir_pins), - Add#(f__, 3, priority_bits), - Add#(d__, 5, priority_bits) + //Mul#(3,no_iterations,ir_bits), + Add#(1,ir_bits,x_ir_bits), + Add#(msb_ir_bits,1,ir_bits), + Add#(msb_ir_pins,1,no_of_ir_pins), + Add#(msb_priority_levels,1,no_of_ir_levels), + Add#(msb_priority_bits,1,priority_bits), + Add#(a__, no_of_ir_levels, data_width), + Add#(b__, ir_bits, data_width), + Add#(c__, no_of_ir_pins, 1024), + Add#(d__, ir_bits, 10), + Add#(f__, no_of_ir_levels, 1024), + Add#(g__, priority_bits, 10), + Add#(h__, no_of_ir_levels, 32), + Add#(e__, 32, data_width) + //Mul#(no_iterations, 3, ir_bits), ); let v_no_of_ir_pins = valueOf(no_of_ir_pins); - let v_priority_bits = valueOf(priority_bits); - let v_msb_priority_bits = valueOf(msb_priority_bits); - let v_msb_priority = valueOf(msb_priority); + let v_ir_bits = valueOf(ir_bits); + let v_msb_ir_bits = valueOf(msb_ir_bits); + let v_msb_ir_pins = valueOf(msb_ir_pins); + let v_msb_priority = valueOf(msb_priority_levels); let v_data_width = valueOf(data_width); //(* noinline *) - /* This function defines the working of priority encoder with 4 bit inputs */ - function Bit#(8) priority_encoder(Bit#(8) inp, Bool alu_free); - Bit#(8) outp = 0; - if(alu_free) begin - if(inp[0]==1) - outp[0] = 1'b1; - else if(inp[1]==1) - outp[1] = 1'b1; - else if(inp[2]==1) - outp[2] = 1'b1; - else if(inp[3]==1) - outp[3] = 1'b1; - else if(inp[4]==1) - outp[4] = 1'b1; - else if(inp[5]==1) - outp[5] = 1'b1; - else if(inp[6]==1) - outp[6] = 1'b1; - else if(inp[7]==1) - outp[7] = 1'b1; - end - - return outp; - endfunction - - function bit any_req(Bit#(8) inp); - return inp[0] | inp[1] | inp[2] | inp[3] | inp[4] | inp[5] | inp[6] | inp[7]; - endfunction - - /* Encodes the grant vector */ - function Bit#(x_priority_bits) encoder(Bit#(no_of_ir_pins) inp); - Bit#(priority_bits) outp = 0; - bit outp_valid = 1'b1; - for(Integer i = 0; i < v_no_of_ir_pins; i = i+1) begin - if(inp[i]==1) - outp = fromInteger(i); - end - return {outp_valid,outp}; - endfunction - - function Reg#(t) readOnlyReg(t r); - return (interface Reg; - method t _read = r; - method Action _write(t x) = noAction; - endinterface); - endfunction - - /* Request vectors are passed down the tree and the grants are given back */ - function Bit#(no_of_ir_pins) encoder_tree(Bit#(no_of_ir_pins) inp); - Bit#(no_of_ir_pins) outp = 0; - //request to root - Bit#(8) root_reqs; - - //grant from root - Bit#(8) root_grants; - - for(Integer i=0;i<8;i=i+1) - root_reqs[i] = any_req(inp[8*fromInteger(i)+7:8*fromInteger(i)]); - - root_grants = priority_encoder(root_reqs, True); - - //grants are passed back to leaves - for(Integer i=0;i<8;i=i+1) - outp[8*fromInteger(i)+7:8*fromInteger(i)] = priority_encoder(inp[8*fromInteger(i)+7:8*fromInteger(i)], unpack(root_grants[i])); - return outp; - endfunction Vector#(no_of_ir_pins,Array#(Reg#(Bool))) rg_ip <- replicateM(mkCReg(2,False)); Reg#(Bool) rg_ie[v_no_of_ir_pins]; @@ -156,57 +101,117 @@ module mkplic(Ifc_PLIC#(addr_width,word_size,no_of_ir_pins)) rg_ie[i] = readOnlyReg(True); else rg_ie[i] <- mkReg(False); - Reg#(Bit#(32)) rg_priority_low[v_no_of_ir_pins]; + Reg#(Bit#(no_of_ir_levels)) rg_priority_low[v_no_of_ir_pins]; for(Integer i =0; i < v_no_of_ir_pins; i=i+1) if(i==28 || i == 29) - rg_priority_low[i] = readOnlyReg(32'h00000001); + rg_priority_low[i] = readOnlyReg(1); else rg_priority_low[i] <- mkConfigReg(0); - Reg#(Bit#(no_of_ir_pins)) rg_priority[v_no_of_ir_pins]; + Reg#(Bit#(32)) rg_priority[v_no_of_ir_pins]; for(Integer i=0;i < v_no_of_ir_pins;i=i+1) rg_priority[i] = concatReg2(readOnlyReg(0), rg_priority_low[i]); - Reg#(Bit#(5)) rg_priority_threshold_low <- mkReg(0); - Reg#(Bit#(priority_bits)) rg_priority_threshold = concatReg2(readOnlyReg(0),rg_priority_threshold_low); - Reg#(Bit#(priority_bits)) rg_interrupt_id <- mkConfigReg(0); + Reg#(Bit#(no_of_ir_levels)) rg_priority_threshold <- mkReg(0); + Reg#(Bit#(ir_bits)) rg_interrupt_id <- mkConfigReg(0); Reg#(Bool) rg_interrupt_valid <- mkConfigReg(False); - Reg#(Maybe#(Bit#(priority_bits))) rg_completion_id <- mkReg(tagged Invalid); + Reg#(Maybe#(Bit#(ir_bits))) rg_completion_id <- mkReg(tagged Invalid); + Reg#(Bit#(no_of_ir_pins)) rg_total_priority <- mkReg(0); + Reg#(Bit#(1)) rg_plic_state <- mkReg(0); //TODO put an enum later + Reg#(Bit#(no_of_ir_levels)) rg_winner_priority <- mkReg(0); + Ifc_encoder#(no_of_ir_levels) ir_priority_encoder <- mkencoder(); + Ifc_encoder#(no_of_ir_pins) irencoder <- mkencoder(); - rule rl_prioritise; + rule rl_prioritise(rg_plic_state==0); Bit#(priority_bits) winner_priority = 0; - Bit#(priority_bits) winner_interrupts = 0; - Bit#(x_priority_bits) ir_id_valid = 0; - Bit#(no_of_ir_pins) lv_priority = 0; + Bit#(ir_bits) winner_interrupts = 0; + Bit#(x_ir_bits) ir_id_valid = 0; + Bit#(no_of_ir_levels) lv_priority = 0; Bit#(no_of_ir_pins) lv_total_priority = 0; for(Integer i = 0; i < v_no_of_ir_pins; i = i + 1) begin if(rg_ip[i][1] && rg_ie[i]) begin - lv_priority = lv_priority | rg_priority[i]; - winner_interrupts = fromInteger(i); + lv_priority = lv_priority | truncate(rg_priority[i]); `ifdef verbose $display($time,"\tInterrupt id %d and priority is %d", i, lv_priority);`endif end end - winner_priority = encoder(encoder_tree(lv_priority))[v_msb_priority:0]; + winner_priority = ir_priority_encoder.encode(lv_priority); `ifdef verbose $display($time,"\t winner priority is %d", winner_priority);`endif for(Integer i = 0; i < v_no_of_ir_pins; i = i + 1) begin if(rg_priority[i][winner_priority] == 1 && rg_ip[i][1] && rg_ie[i]) lv_total_priority[i] = 1; end - if(lv_total_priority!=0) - winner_interrupts = encoder(encoder_tree(lv_total_priority))[v_msb_priority:0]; - if(winner_interrupts!=0) begin - ir_id_valid = encoder(rg_priority[winner_interrupts]); - if(winner_priority <= rg_priority_threshold) - begin - - `ifdef verbose $display("Interrupt valid");`endif - rg_interrupt_id <= winner_interrupts; - rg_interrupt_valid <= True; - $display($time,"\t The highest priority interrupt is %d and the priority is ", winner_interrupts, winner_priority); - end + if(lv_total_priority!=0) begin + rg_total_priority <= lv_total_priority; + rg_plic_state <= 1; + Bit#(no_of_ir_levels) lv_winner_priority = 0; + lv_winner_priority[winner_priority] = 1; + rg_winner_priority <= lv_winner_priority; end endrule + rule rl_encoder(rg_plic_state==1); + Bit#(ir_bits) interrupt_id = irencoder.encode(rg_total_priority); + if(interrupt_id!=0 && rg_priority_threshold >= rg_winner_priority) begin + `ifdef verbose $display("Interrupt valid");`endif + rg_interrupt_id <= interrupt_id; + rg_interrupt_valid <= True; + $display($time,"\t The highest priority interrupt is %d and the priority is ", interrupt_id, rg_winner_priority); + end + rg_plic_state <= 0; + + + //if(lv_total_priority!=0) + //winner_interrupts = encoder(encoder_tree(lv_total_priority))[v_msb_priority:0]; + //if(winner_interrupts!=0) begin + // if(winner_priority <= rg_priority_threshold) + // begin + // + // `ifdef verbose $display("Interrupt valid");`endif + // rg_interrupt_id <= winner_interrupts; + // rg_interrupt_valid <= True; + // $display($time,"\t The highest priority interrupt is %d and the priority is ", winner_interrupts, winner_priority); + // end + //end + endrule + + + //for(Integer i = 0; i> 2; if(mem_req.ld_st == Load) begin - source_id = address[v_msb_priority:0]; + source_id = address[v_msb_ir_bits:0]; `ifdef verbose $display($time,"\tPLIC : source %d Priority set to %h", source_id, mem_req.write_data);`endif data_return = zeroExtend(rg_priority[source_id]); end else if(mem_req.ld_st == Store) begin - Bit#(no_of_ir_pins) store_data; + Bit#(data_width) store_data; if(mem_req.byte_offset==0) - store_data=mem_req.write_data[v_msb_priority_bits:0]; + store_data=mem_req.write_data[v_msb_ir_pins:0]; else store_data=mem_req.write_data[v_data_width-1:v_data_width-v_no_of_ir_pins]; mem_req.byte_offset = mem_req.byte_offset >> 2; - source_id = address[v_msb_priority:0] | zeroExtend(mem_req.byte_offset); + source_id = address[v_msb_ir_bits:0]; $display($time,"\tPLIC : source %d Priority set to %h", source_id, store_data); - rg_priority[source_id] <= store_data; + rg_priority[source_id] <= truncate(store_data); end end - //else if(address < 'h0C002000) begin - else if(address<`PLICBase+'h2000)begin + else if(address < 'h0C002000) begin if(mem_req.ld_st == Load) begin - source_id = address[v_msb_priority:0]; + source_id = address[v_msb_ir_bits:0]; source_id = source_id << 3; for(Integer i = 0; i < 8; i = i+1) data_return[i] = pack(rg_ip[source_id + fromInteger(i)][1]); end else if(mem_req.ld_st == Store) begin - source_id = zeroExtend(mem_req.byte_offset); + source_id = address[v_msb_ir_bits:0]; source_id = source_id << 3; for(Integer i = 0; i < 8; i = i+1) begin `ifdef verbose $display($time,"\tPLIC : pending interrupt %b id %d", mem_req.write_data[i], source_id);`endif @@ -268,17 +271,16 @@ interface ifc_prog_reg = interface Ifc_program_registers; end end end - //else if(address < 'h0C020000) begin - else if(address < `PLICBase+'h20000)begin + else if(address < 'h0C020000) begin if(mem_req.ld_st == Load) begin - source_id = address[v_msb_priority:0]; + source_id = address[v_msb_ir_bits:0]; source_id = source_id << 3; for(Integer i = 0; i < 8; i = i+1) data_return[i] = pack(rg_ie[source_id + fromInteger(i)]); `ifdef verbose $display($time,"PLIC: Printing Source Enable Interrupt: %h data_return: %h",source_id,data_return); `endif end else if(mem_req.ld_st == Store) begin - source_id = zeroExtend(mem_req.byte_offset); + source_id = address[v_msb_ir_bits:0]; source_id = source_id << 3; for(Integer i = 0; i < 8; i = i+1) begin `ifdef verbose $display($time,"\tPLIC : enabled interrupt %b id %d", mem_req.write_data[i], source_id);`endif @@ -286,23 +288,21 @@ interface ifc_prog_reg = interface Ifc_program_registers; end end end - // else if(address == 'hC200000) begin - else if(address ==`PLICBase+'h200000)begin + else if(address == 'hC200000) begin if(mem_req.ld_st == Load) begin data_return = zeroExtend(rg_priority_threshold); end else if(mem_req.ld_st == Store) rg_priority_threshold <= mem_req.write_data[v_msb_priority:0]; end - // else if(address == 'hC200004) begin - else if(address == `PLICBase+'h200004)begin + else if(address == 'hC200004) begin if(mem_req.ld_st == Load) begin data_return = zeroExtend(rg_interrupt_id); rg_ip[rg_interrupt_id][1] <= False; `ifdef verbose $display($time,"rg_ip is made false here"); `endif end else if(mem_req.ld_st == Store) begin - source_id = mem_req.write_data[v_msb_priority:0]; + source_id = mem_req.write_data[v_msb_ir_bits:0]; rg_completion_id <= tagged Valid source_id; `ifdef verbose $display("rg_completion_id is made tagged valid and completion is signaled-- source_id: %d",source_id); `endif end @@ -339,7 +339,7 @@ endinterface module mkplicperipheral(Ifc_PLIC_AXI); AXI4_Lite_Slave_Xactor_IFC #(`PADDR, `Reg_width, `USERSPACE) s_xactor_plic <- mkAXI4_Lite_Slave_Xactor; -Ifc_PLIC#(`PADDR, `DCACHE_WORD_SIZE, `INTERRUPT_PINS) plic <- mkplic(); +Ifc_PLIC#(`PADDR, `DCACHE_WORD_SIZE, `INTERRUPT_PINS, `INTERRUPT_LEVELS) plic <- mkplic(); (*preempts="rl_config_plic_reg_read, rl_config_plic_reg_write"*) rule rl_config_plic_reg_write; @@ -362,11 +362,12 @@ Ifc_PLIC#(`PADDR, `DCACHE_WORD_SIZE, `INTERRUPT_PINS) plic <- mkplic(); let ar <- pop_o(s_xactor_plic.o_rd_addr); let x <- plic.ifc_prog_reg.prog_reg(UncachedMemReq{address : ar.araddr, transfer_size : 'd3, u_signed : 0, byte_offset : 0, ld_st : Load}); -// if(ar.arsize==3'd0) -// x = duplicate(x[7:0]); -// else if(ar.arsize==3'd1) -// x = duplicate(x[15:0]); -// else if(ar.arsize==3'd2) + if(ar.arsize==3'd0) + x = duplicate(x[7:0]); + else if(ar.arsize==3'd1) + x = duplicate(x[15:0]); + else if(ar.arsize==3'd2) + x = duplicate(x[7:0]); let r = AXI4_Lite_Rd_Data {rresp: AXI4_LITE_OKAY, rdata: duplicate(x), ruser: 0}; s_xactor_plic.i_rd_data.enq(r);