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
|
||||
localparam N=`PLIC_NUM_SRC;
|
||||
|
||||
logic memread, memwrite, initTrans;
|
||||
logic [27:0] entry, A;
|
||||
logic memwrite, initTrans;
|
||||
logic [27:0] entry, entryd;
|
||||
logic [31:0] Din, Dout;
|
||||
logic [N:1] requests;
|
||||
|
||||
logic [2:0] intPriority[N:1];
|
||||
@ -66,17 +67,34 @@ module plic (
|
||||
logic [7:1] threshMask;
|
||||
|
||||
// AHB I/O
|
||||
assign entry = {HADDR[27:2],2'b0};
|
||||
assign initTrans = HREADY & HSELPLIC & (HTRANS != 2'b00);
|
||||
flopenrc #(1) memreadreg(HCLK, ~HRESETn, memread&HREADY, (memread&HREADY)|initTrans, HSELPLIC & ~HWRITE, memread);
|
||||
flopenrc #(1) memwritereg(HCLK, ~HRESETn, memwrite&HREADY, (memwrite&HREADY)|initTrans, HSELPLIC & HWRITE, memwrite);
|
||||
flopenr #(28) haddrreg(HCLK, ~HRESETn,initTrans, HADDR, A);
|
||||
flopr #(1) memwriteflop(HCLK, ~HRESETn, initTrans & HWRITE, memwrite);
|
||||
flopr #(28) entrydflop(HCLK, ~HRESETn, entry, entryd);
|
||||
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
|
||||
assign #2 entry = {A[27:2], 2'b00};
|
||||
// account for subword read/write circuitry
|
||||
// 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;
|
||||
generate
|
||||
// priority registers
|
||||
@ -84,89 +102,62 @@ module plic (
|
||||
always @(posedge HCLK,negedge HRESETn)
|
||||
if (~HRESETn)
|
||||
intPriority[i] <= 3'b0;
|
||||
else if (entry == 28'hc000000+4*i) // *** make sure this does not synthesize into N 28-bit equality comparators
|
||||
if (memwrite) intPriority[i] <= #1 HWDATA[2:0];
|
||||
else HREADPLIC <= #1 {{(`XLEN-3){1'b0}},intPriority[i]};
|
||||
else begin
|
||||
if (entry == 28'hc000000+4*i) // *** make sure this does not synthesize into N 28-bit equality comparators
|
||||
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
|
||||
if (N<32 && `XLEN==32)
|
||||
if (N<32)
|
||||
always @(posedge HCLK,negedge HRESETn)
|
||||
if (~HRESETn)
|
||||
intEn <= {N{1'b0}};
|
||||
else
|
||||
case(entry)
|
||||
28'hc001000: HREADPLIC <= #1 {{(31-N){1'b0}},intPending[N:1],1'b0};
|
||||
28'hc002000: if (memwrite) intEn[N:1] <= #1 HWDATA[N:1];
|
||||
else HREADPLIC <= #1 {{(31-N){1'b0}},intEn[N:1],1'b0};
|
||||
endcase
|
||||
else if (N>=32 && `XLEN==32)
|
||||
else begin
|
||||
if (entry == 28'hc001000)
|
||||
Dout <= #1 {{(31-N){1'b0}},intPending[N:1],1'b0};
|
||||
if (entry == 28'hc002000)
|
||||
Dout <= #1 {{(31-N){1'b0}},intEn[N:1],1'b0};
|
||||
if ((entryd == 28'hc002000) && memwrite)
|
||||
intEn[N:1] <= #1 Din[N:1];
|
||||
end
|
||||
else // N>=32
|
||||
always @(posedge HCLK,negedge HRESETn)
|
||||
if (~HRESETn)
|
||||
intEn <= {N{1'b0}};
|
||||
else
|
||||
case(entry)
|
||||
28'hc001000: HREADPLIC <= #1 {intPending[31:1],1'b0};
|
||||
28'hc001004: HREADPLIC <= #1 {{(63-N){1'b0}},intPending[N:32]};
|
||||
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[31:0];
|
||||
else HREADPLIC <= #1 {{(63-N){1'b0}},intEn[N:32]};
|
||||
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 {{(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
|
||||
else begin
|
||||
if (entry == 28'hc001000)
|
||||
Dout <= #1 {intPending[31:1],1'b0};
|
||||
if (entry == 28'hc001004)
|
||||
Dout <= #1 {{(63-N){1'b0}},intPending[N:32]};
|
||||
if (entry == 28'hc002000)
|
||||
Dout <= #1 {intEn[31:1],1'b0};
|
||||
if (entry == 28'hc002004)
|
||||
Dout <= #1 {{(63-N){1'b0}},intEn[N:32]};
|
||||
if ((entryd == 28'hc002000) && memwrite)
|
||||
intEn[31:1] <= #1 Din[31:1];
|
||||
if ((entryd == 28'hc002004) && memwrite)
|
||||
intEn[N:32] <= #1 Din[31:0];
|
||||
end
|
||||
|
||||
// threshold and claim/complete registers
|
||||
if (`XLEN==32)
|
||||
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 {{29{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};
|
||||
intInProgress <= #1 intInProgress | (1'b1 << (intClaim-1)); // claimed requests are currently in progress of being serviced until they are completed
|
||||
end
|
||||
endcase
|
||||
else if (`XLEN==64)
|
||||
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
|
||||
always @(posedge HCLK, negedge HRESETn)
|
||||
if (~HRESETn) begin
|
||||
intThreshold<=3'b0;
|
||||
intInProgress <= {N{1'b0}};
|
||||
end else begin
|
||||
if (entry == 28'hc200000)
|
||||
Dout <= #1 {29'b0,intThreshold[2:0]};
|
||||
if ((entryd == 28'hc200000) && memwrite)
|
||||
intThreshold[2:0] <= #1 Din[2:0];
|
||||
if (entry == 28'hc200004) begin
|
||||
Dout <= #1 {26'b0,intClaim};
|
||||
intInProgress <= #1 intInProgress | (1'b1 << (intClaim-1)); // claimed requests are currently in progress of being serviced until they are completed
|
||||
end
|
||||
if ((entryd == 28'hc200004) && memwrite)
|
||||
intInProgress <= #1 intInProgress & ~(1'b1 << (Din[5:0]-1)); // lower "InProgress" to signify completion
|
||||
end
|
||||
endgenerate
|
||||
|
||||
// connect sources to requests
|
||||
|
Loading…
Reference in New Issue
Block a user