plic subword access compliance

This commit is contained in:
bbracker 2021-04-04 23:10:33 -04:00
parent f41b5a2d38
commit 8f4da826fb

View File

@ -50,8 +50,9 @@ module plic (
// N in config should not exceed 63; does not inlcude source 0, which does not connect to anything according to spec // N in config should not exceed 63; does not inlcude source 0, which does not connect to anything according to spec
localparam N=`PLIC_NUM_SRC; localparam N=`PLIC_NUM_SRC;
logic memread, memwrite, initTrans; logic memwrite, initTrans;
logic [27:0] entry, A; logic [27:0] entry, entryd;
logic [31:0] Din, Dout;
logic [N:1] requests; logic [N:1] requests;
logic [2:0] intPriority[N:1]; logic [2:0] intPriority[N:1];
@ -66,17 +67,34 @@ module plic (
logic [7:1] threshMask; logic [7:1] threshMask;
// AHB I/O // AHB I/O
assign entry = {HADDR[27:2],2'b0};
assign initTrans = HREADY & HSELPLIC & (HTRANS != 2'b00); assign initTrans = HREADY & HSELPLIC & (HTRANS != 2'b00);
flopenrc #(1) memreadreg(HCLK, ~HRESETn, memread&HREADY, (memread&HREADY)|initTrans, HSELPLIC & ~HWRITE, memread); flopr #(1) memwriteflop(HCLK, ~HRESETn, initTrans & HWRITE, memwrite);
flopenrc #(1) memwritereg(HCLK, ~HRESETn, memwrite&HREADY, (memwrite&HREADY)|initTrans, HSELPLIC & HWRITE, memwrite); flopr #(28) entrydflop(HCLK, ~HRESETn, entry, entryd);
flopenr #(28) haddrreg(HCLK, ~HRESETn,initTrans, HADDR, A);
assign HRESPPLIC = 0; // OK assign HRESPPLIC = 0; // OK
assign HREADYPLIC = 1'b1; // will need to be modified if PLIC ever needs more than 1 cycle to do something assign HREADYPLIC = 1'b1; // PLIC never takes >1 cycle to respond
// word aligned reads // account for subword read/write circuitry
assign #2 entry = {A[27:2], 2'b00}; // Note PLIC registers are 32 bits no matter what; access them with LW SW.
generate
if (`XLEN == 64) begin
always_comb
if (entryd[2]) begin
Din = HWDATA[63:32];
HREADPLIC = {Dout,32'b0};
end else begin
Din = HWDATA[31:0];
HREADPLIC = {32'b0,Dout};
end
end else begin // 32-bit
always_comb begin
Din = HWDATA[31:0];
HREADPLIC = Dout;
end
end
endgenerate
// register access // register interface
genvar i; genvar i;
generate generate
// priority registers // priority registers
@ -84,89 +102,62 @@ module plic (
always @(posedge HCLK,negedge HRESETn) always @(posedge HCLK,negedge HRESETn)
if (~HRESETn) if (~HRESETn)
intPriority[i] <= 3'b0; intPriority[i] <= 3'b0;
else if (entry == 28'hc000000+4*i) // *** make sure this does not synthesize into N 28-bit equality comparators else begin
if (memwrite) intPriority[i] <= #1 HWDATA[2:0]; if (entry == 28'hc000000+4*i) // *** make sure this does not synthesize into N 28-bit equality comparators
else HREADPLIC <= #1 {{(`XLEN-3){1'b0}},intPriority[i]}; Dout <= #1 {{(`XLEN-3){1'b0}},intPriority[i]};
if ((entryd == 28'hc000000+4*i) && memwrite)
intPriority[i] <= #1 Din[2:0];
end
// pending and enable registers // pending and enable registers
if (N<32 && `XLEN==32) if (N<32)
always @(posedge HCLK,negedge HRESETn) always @(posedge HCLK,negedge HRESETn)
if (~HRESETn) if (~HRESETn)
intEn <= {N{1'b0}}; intEn <= {N{1'b0}};
else else begin
case(entry) if (entry == 28'hc001000)
28'hc001000: HREADPLIC <= #1 {{(31-N){1'b0}},intPending[N:1],1'b0}; Dout <= #1 {{(31-N){1'b0}},intPending[N:1],1'b0};
28'hc002000: if (memwrite) intEn[N:1] <= #1 HWDATA[N:1]; if (entry == 28'hc002000)
else HREADPLIC <= #1 {{(31-N){1'b0}},intEn[N:1],1'b0}; Dout <= #1 {{(31-N){1'b0}},intEn[N:1],1'b0};
endcase if ((entryd == 28'hc002000) && memwrite)
else if (N>=32 && `XLEN==32) intEn[N:1] <= #1 Din[N:1];
end
else // N>=32
always @(posedge HCLK,negedge HRESETn) always @(posedge HCLK,negedge HRESETn)
if (~HRESETn) if (~HRESETn)
intEn <= {N{1'b0}}; intEn <= {N{1'b0}};
else else begin
case(entry) if (entry == 28'hc001000)
28'hc001000: HREADPLIC <= #1 {intPending[31:1],1'b0}; Dout <= #1 {intPending[31:1],1'b0};
28'hc001004: HREADPLIC <= #1 {{(63-N){1'b0}},intPending[N:32]}; if (entry == 28'hc001004)
28'hc002000: if (memwrite) intEn[31:1] <= #1 HWDATA[31:1]; Dout <= #1 {{(63-N){1'b0}},intPending[N:32]};
else HREADPLIC <= #1 {intEn[31:1],1'b0}; if (entry == 28'hc002000)
28'hc002004: if (memwrite) intEn[N:32] <= #1 HWDATA[31:0]; Dout <= #1 {intEn[31:1],1'b0};
else HREADPLIC <= #1 {{(63-N){1'b0}},intEn[N:32]}; if (entry == 28'hc002004)
endcase Dout <= #1 {{(63-N){1'b0}},intEn[N:32]};
else if (N<32 && `XLEN==64) if ((entryd == 28'hc002000) && memwrite)
always @(posedge HCLK,negedge HRESETn) intEn[31:1] <= #1 Din[31:1];
if (~HRESETn) if ((entryd == 28'hc002004) && memwrite)
intEn <= {N{1'b0}}; intEn[N:32] <= #1 Din[31:0];
else end
case(entry)
28'hc001000: HREADPLIC <= #1 {{(63-N){1'b0}},intPending[N:1],1'b0};
28'hc002000: if (memwrite) intEn[N:1] <= #1 HWDATA[N:1];
else HREADPLIC <= #1 {{(63-N){1'b0}},intEn[N:1],1'b0};
endcase
else if (N>=32 && `XLEN==64)
always @(posedge HCLK,negedge HRESETn)
if (~HRESETn)
intEn <= {N{1'b0}};
else
case(entry)
28'hc001000: HREADPLIC <= #1 {32'b0,intPending[31:1],1'b0};
28'hc001004: HREADPLIC <= #1 {{(63-N){1'b0}},intPending[N:32],32'b0}; // rearranged so that you can access it with lw (when addr%8 = 4, subwordwrite thinks we are looking at the upper half of a 64bit word); *** is this reasonable? Why does SWW work like that anyways?; if we don't mind 32 and 64 bit versions having different memory maps, that might clean things up, but it might also be a departure of spec
28'hc002000: if (memwrite) intEn[31:1] <= #1 HWDATA[31:1];
else HREADPLIC <= #1 {intEn[31:1],1'b0};
28'hc002004: if (memwrite) intEn[N:32] <= #1 HWDATA[63:32];
else HREADPLIC <= #1 {{(63-N){1'b0}},intEn[N:32],32'b0};
endcase
// threshold and claim/complete registers // threshold and claim/complete registers
if (`XLEN==32) always @(posedge HCLK, negedge HRESETn)
always @(posedge HCLK, negedge HRESETn) if (~HRESETn) begin
if (~HRESETn) begin intThreshold<=3'b0;
intThreshold<=3'b0; intInProgress <= {N{1'b0}};
intInProgress <= {N{1'b0}}; end else begin
end else if (entry == 28'hc200000)
case (HADDR) Dout <= #1 {29'b0,intThreshold[2:0]};
28'hc200000: if (memwrite) intThreshold[2:0] <= #1 HWDATA[2:0]; if ((entryd == 28'hc200000) && memwrite)
else HREADPLIC <= #1 {{29{1'b0}},intThreshold[2:0]}; intThreshold[2:0] <= #1 Din[2:0];
28'hc200004: if (memwrite) intInProgress <= #1 intInProgress & ~(1'b1 << (HWDATA[5:0]-1)); // lower "InProgress" to signify completion if (entry == 28'hc200004) begin
else begin Dout <= #1 {26'b0,intClaim};
HREADPLIC <= #1 {{26{1'b0}},intClaim}; intInProgress <= #1 intInProgress | (1'b1 << (intClaim-1)); // claimed requests are currently in progress of being serviced until they are completed
intInProgress <= #1 intInProgress | (1'b1 << (intClaim-1)); // claimed requests are currently in progress of being serviced until they are completed end
end if ((entryd == 28'hc200004) && memwrite)
endcase intInProgress <= #1 intInProgress & ~(1'b1 << (Din[5:0]-1)); // lower "InProgress" to signify completion
else if (`XLEN==64) end
always @(posedge HCLK, negedge HRESETn)
if (~HRESETn) begin
intThreshold<=3'b0;
intInProgress <= {N{1'b0}};
end else
case (HADDR)
28'hc200000: if (memwrite) intThreshold[2:0] <= #1 HWDATA[2:0];
else HREADPLIC <= #1 {{61{1'b0}},intThreshold[2:0]};
28'hc200004: if (memwrite) intInProgress <= #1 intInProgress & ~(1'b1 << (HWDATA[5:0]-1)); // lower "InProgress" to signify completion
else begin
HREADPLIC <= #1 {{26{1'b0}},intClaim,32'b0};
intInProgress <= #1 intInProgress | (1'b1 << (intClaim-1)); // claimed requests are currently in progress of being serviced until they are completed
end
endcase
endgenerate endgenerate
// connect sources to requests // connect sources to requests