mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
plic subword access compliance
This commit is contained in:
parent
f41b5a2d38
commit
8f4da826fb
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user