forked from Github_Repos/cvw
plic implementation optimizations
This commit is contained in:
parent
979a9bf037
commit
bf6337f2f7
@ -48,7 +48,7 @@ module plic (
|
|||||||
localparam N=`PLIC_NUM_SRC; // should not exceed 63; does not inlcude source 0, which does not connect to anything according to spec
|
localparam N=`PLIC_NUM_SRC; // should not exceed 63; does not inlcude source 0, which does not connect to anything according to spec
|
||||||
|
|
||||||
logic memwrite, memread, initTrans;
|
logic memwrite, memread, initTrans;
|
||||||
logic [27:0] entry, entryd;
|
logic [23:0] entry, entryd;
|
||||||
logic [31:0] Din, Dout;
|
logic [31:0] Din, Dout;
|
||||||
logic [N:1] requests;
|
logic [N:1] requests;
|
||||||
|
|
||||||
@ -66,12 +66,12 @@ module plic (
|
|||||||
// =======
|
// =======
|
||||||
// AHB I/O
|
// AHB I/O
|
||||||
// =======
|
// =======
|
||||||
assign entry = {HADDR[27:2],2'b0};
|
assign entry = {HADDR[23:2],2'b0};
|
||||||
assign initTrans = HREADY & HSELPLIC & (HTRANS != 2'b00);
|
assign initTrans = HREADY & HSELPLIC & (HTRANS != 2'b00);
|
||||||
assign memread = initTrans & ~HWRITE;
|
assign memread = initTrans & ~HWRITE;
|
||||||
// entryd and memwrite are delayed by a cycle because AHB controller waits a cycle before outputting write data
|
// entryd and memwrite are delayed by a cycle because AHB controller waits a cycle before outputting write data
|
||||||
flopr #(1) memwriteflop(HCLK, ~HRESETn, initTrans & HWRITE, memwrite);
|
flopr #(1) memwriteflop(HCLK, ~HRESETn, initTrans & HWRITE, memwrite);
|
||||||
flopr #(28) entrydflop(HCLK, ~HRESETn, entry, entryd);
|
flopr #(24) entrydflop(HCLK, ~HRESETn, entry, entryd);
|
||||||
assign HRESPPLIC = 0; // OK
|
assign HRESPPLIC = 0; // OK
|
||||||
assign HREADYPLIC = 1'b1; // PLIC never takes >1 cycle to respond
|
assign HREADYPLIC = 1'b1; // PLIC never takes >1 cycle to respond
|
||||||
|
|
||||||
@ -109,33 +109,33 @@ module plic (
|
|||||||
end else begin
|
end else begin
|
||||||
if (memwrite)
|
if (memwrite)
|
||||||
casez(entryd)
|
casez(entryd)
|
||||||
28'hc0000??: intPriority[entryd[7:2]] <= #1 Din[2:0];
|
24'h0000??: intPriority[entryd[7:2]] <= #1 Din[2:0];
|
||||||
`ifdef PLIC_NUM_SRC_LT_32
|
`ifdef PLIC_NUM_SRC_LT_32
|
||||||
28'hc002000: intEn[N:1] <= #1 Din[N:1];
|
24'h002000: intEn[N:1] <= #1 Din[N:1];
|
||||||
`endif
|
`endif
|
||||||
`ifndef PLIC_NUM_SRC_LT_32
|
`ifndef PLIC_NUM_SRC_LT_32
|
||||||
28'hc002000: intEn[31:1] <= #1 Din[31:1];
|
24'h002000: intEn[31:1] <= #1 Din[31:1];
|
||||||
28'hc002004: intEn[N:32] <= #1 Din[31:0];
|
24'h002004: intEn[N:32] <= #1 Din[31:0];
|
||||||
`endif
|
`endif
|
||||||
28'hc200000: intThreshold[2:0] <= #1 Din[2:0];
|
24'h200000: intThreshold[2:0] <= #1 Din[2:0];
|
||||||
28'hc200004: intInProgress <= #1 intInProgress & ~(1'b1 << (Din[5:0]-1)); // lower "InProgress" to signify completion
|
24'h200004: intInProgress <= #1 intInProgress & ~(1'b1 << (Din[5:0]-1)); // lower "InProgress" to signify completion
|
||||||
endcase
|
endcase
|
||||||
// reading
|
// reading
|
||||||
if (memread)
|
if (memread)
|
||||||
casez(entry)
|
casez(entry)
|
||||||
28'hc0000??: Dout <= #1 {{(`XLEN-3){1'b0}},intPriority[entry[7:2]]};
|
24'h0000??: Dout <= #1 {{(`XLEN-3){1'b0}},intPriority[entry[7:2]]};
|
||||||
`ifdef PLIC_NUM_SRC_LT_32
|
`ifdef PLIC_NUM_SRC_LT_32
|
||||||
28'hc001000: Dout <= #1 {{(31-N){1'b0}},intPending[N:1],1'b0};
|
24'h001000: Dout <= #1 {{(31-N){1'b0}},intPending[N:1],1'b0};
|
||||||
28'hc002000: Dout <= #1 {{(31-N){1'b0}},intEn[N:1],1'b0};
|
24'h002000: Dout <= #1 {{(31-N){1'b0}},intEn[N:1],1'b0};
|
||||||
`endif
|
`endif
|
||||||
`ifndef PLIC_NUM_SRC_LT_32
|
`ifndef PLIC_NUM_SRC_LT_32
|
||||||
28'hc001000: Dout <= #1 {intPending[31:1],1'b0};
|
24'h001000: Dout <= #1 {intPending[31:1],1'b0};
|
||||||
28'hc001004: Dout <= #1 {{(63-N){1'b0}},intPending[N:32]};
|
24'h001004: Dout <= #1 {{(63-N){1'b0}},intPending[N:32]};
|
||||||
28'hc002000: Dout <= #1 {intEn[31:1],1'b0};
|
24'h002000: Dout <= #1 {intEn[31:1],1'b0};
|
||||||
28'hc002004: Dout <= #1 {{(63-N){1'b0}},intEn[N:32]};
|
24'h002004: Dout <= #1 {{(63-N){1'b0}},intEn[N:32]};
|
||||||
`endif
|
`endif
|
||||||
28'hc200000: Dout <= #1 {29'b0,intThreshold[2:0]};
|
24'h200000: Dout <= #1 {29'b0,intThreshold[2:0]};
|
||||||
28'hc200004: begin
|
24'h200004: begin
|
||||||
Dout <= #1 {26'b0,intClaim};
|
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
|
intInProgress <= #1 intInProgress | (1'b1 << (intClaim-1)); // claimed requests are currently in progress of being serviced until they are completed
|
||||||
end
|
end
|
||||||
@ -160,7 +160,7 @@ module plic (
|
|||||||
// pending updates
|
// pending updates
|
||||||
// *** verify that this matches the expectations of the things that make requests (in terms of timing, edge-triggered vs level-triggered)
|
// *** verify that this matches the expectations of the things that make requests (in terms of timing, edge-triggered vs level-triggered)
|
||||||
assign nextIntPending = (intPending | (requests & ~intInProgress)) // requests should raise intPending except when their service routine is already in progress
|
assign nextIntPending = (intPending | (requests & ~intInProgress)) // requests should raise intPending except when their service routine is already in progress
|
||||||
& ~(((entry == 28'hc200004) && memread) << (intClaim-1)); // clear pending bit when claim register is read
|
& ~(((entry == 24'h200004) && memread) << (intClaim-1)); // clear pending bit when claim register is read
|
||||||
flopr #(N) intPendingFlop(HCLK,~HRESETn,nextIntPending,intPending);
|
flopr #(N) intPendingFlop(HCLK,~HRESETn,nextIntPending,intPending);
|
||||||
|
|
||||||
// pending array - indexed by priority_lvl x source_ID
|
// pending array - indexed by priority_lvl x source_ID
|
||||||
@ -212,22 +212,15 @@ module plic (
|
|||||||
end
|
end
|
||||||
|
|
||||||
// create threshold mask
|
// create threshold mask
|
||||||
// *** I think this commented out version would be nice, but linter complains about circular logic
|
always_comb begin
|
||||||
//assign threshMask[7:1] = {~(7==intThreshold),
|
threshMask[7] = ~(7==intThreshold);
|
||||||
// ~(6==intThreshold) & threshMask[7],
|
threshMask[6] = ~(6==intThreshold) & threshMask[7];
|
||||||
// ~(5==intThreshold) & threshMask[6],
|
threshMask[5] = ~(5==intThreshold) & threshMask[6];
|
||||||
// ~(4==intThreshold) & threshMask[5],
|
threshMask[4] = ~(4==intThreshold) & threshMask[5];
|
||||||
// ~(3==intThreshold) & threshMask[4],
|
threshMask[3] = ~(3==intThreshold) & threshMask[4];
|
||||||
// ~(2==intThreshold) & threshMask[3],
|
threshMask[2] = ~(2==intThreshold) & threshMask[3];
|
||||||
// ~(1==intThreshold) & threshMask[2]};
|
threshMask[1] = ~(1==intThreshold) & threshMask[2];
|
||||||
// *** verify that this alternate version does not synthesize to 7 separate comparators
|
end
|
||||||
assign threshMask[7:1] = {(7>intThreshold),
|
|
||||||
(6>intThreshold),
|
|
||||||
(5>intThreshold),
|
|
||||||
(4>intThreshold),
|
|
||||||
(3>intThreshold),
|
|
||||||
(2>intThreshold),
|
|
||||||
(1>intThreshold)};
|
|
||||||
// is the max priority > threshold?
|
// is the max priority > threshold?
|
||||||
// *** would it be any better to first priority encode maxPriority into binary and then ">" with threshold?
|
// *** would it be any better to first priority encode maxPriority into binary and then ">" with threshold?
|
||||||
assign ExtIntM = |(threshMask & pendingPGrouped);
|
assign ExtIntM = |(threshMask & pendingPGrouped);
|
||||||
|
Loading…
Reference in New Issue
Block a user