forked from Github_Repos/cvw
1st attempt at multiple channel PLIC
This commit is contained in:
parent
aa60b57fb3
commit
4b376e2834
@ -101,10 +101,12 @@ then
|
|||||||
set logging on
|
set logging on
|
||||||
# Priority Levels for sources 1 thru 63
|
# Priority Levels for sources 1 thru 63
|
||||||
x/63xw 0x0C000004
|
x/63xw 0x0C000004
|
||||||
# Interrupt Enables
|
# Interrupt Enables for sources 1 thru 63 for contexts 0 and 1
|
||||||
x/2xw 0x0C020000
|
x/2xw 0x0C020000
|
||||||
# Global Priority Threshold
|
x/2xw 0x0C020080
|
||||||
|
# Global Priority Threshold for contexts 0 and 1
|
||||||
x/1xw 0x0C200000
|
x/1xw 0x0C200000
|
||||||
|
x/1xw 0x0C201000
|
||||||
set logging off
|
set logging off
|
||||||
shell echo \"GDB storing RAM to $rawRamFile\"
|
shell echo \"GDB storing RAM to $rawRamFile\"
|
||||||
dump binary memory $rawRamFile 0x80000000 0xffffffff
|
dump binary memory $rawRamFile 0x80000000 0xffffffff
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#! /usr/bin/python3
|
#! /usr/bin/python3
|
||||||
import sys, os
|
import sys, os
|
||||||
|
from functools import reduce
|
||||||
|
|
||||||
################
|
################
|
||||||
# Helper Funcs #
|
# Helper Funcs #
|
||||||
@ -21,6 +22,9 @@ def tokenize(string):
|
|||||||
token = token + char
|
token = token + char
|
||||||
return tokens
|
return tokens
|
||||||
|
|
||||||
|
def strip0x(num):
|
||||||
|
return num[2:]
|
||||||
|
|
||||||
def stripZeroes(num):
|
def stripZeroes(num):
|
||||||
num = num.strip('0')
|
num = num.strip('0')
|
||||||
if num=='':
|
if num=='':
|
||||||
@ -42,7 +46,7 @@ if not os.path.exists(rawPlicStateFile):
|
|||||||
sys.exit('Error input file '+rawPlicStateFile+'not found')
|
sys.exit('Error input file '+rawPlicStateFile+'not found')
|
||||||
|
|
||||||
with open(rawPlicStateFile, 'r') as rawPlicStateFile:
|
with open(rawPlicStateFile, 'r') as rawPlicStateFile:
|
||||||
plicIntPriorityArray=[]
|
plicIntPriorityArray = [] # iterates over number of different sources
|
||||||
# 0x0C000004 thru 0x0C000010
|
# 0x0C000004 thru 0x0C000010
|
||||||
plicIntPriorityArray += tokenize(rawPlicStateFile.readline())[1:]
|
plicIntPriorityArray += tokenize(rawPlicStateFile.readline())[1:]
|
||||||
# 0x0C000014 thru 0x0C000020
|
# 0x0C000014 thru 0x0C000020
|
||||||
@ -76,20 +80,30 @@ with open(rawPlicStateFile, 'r') as rawPlicStateFile:
|
|||||||
# 0x0C0000f4 thru 0x0C0000fc
|
# 0x0C0000f4 thru 0x0C0000fc
|
||||||
plicIntPriorityArray += tokenize(rawPlicStateFile.readline())[1:]
|
plicIntPriorityArray += tokenize(rawPlicStateFile.readline())[1:]
|
||||||
|
|
||||||
|
plicIntEnableArray = [] # iterates over number of different contexts
|
||||||
# 0x0C020000 thru 0x0C020004
|
# 0x0C020000 thru 0x0C020004
|
||||||
plicIntEnable = tokenize(rawPlicStateFile.readline())[1:]
|
plicIntEnable = tokenize(rawPlicStateFile.readline())[1:]
|
||||||
|
plicIntEnable = map(strip0x,plicIntEnable)
|
||||||
|
plicIntEnableArray.append(reduce(lambda x,y: x+y,plicIntEnable))
|
||||||
|
# 0x0C020080 thru 0x0C020084
|
||||||
|
plicIntEnable = tokenize(rawPlicStateFile.readline())[1:]
|
||||||
|
plicIntEnable = map(strip0x,plicIntEnable)
|
||||||
|
plicIntEnableArray.append(reduce(lambda x,y: x+y,plicIntEnable))
|
||||||
|
|
||||||
|
plicIntPriorityThresholdArray = [] # iterates over number of different contexts
|
||||||
# 0x0C200000
|
# 0x0C200000
|
||||||
plicIntPriorityThreshold = tokenize(rawPlicStateFile.readline())[1:]
|
plicIntPriorityThresholdArray += tokenize(rawPlicStateFile.readline())[1:]
|
||||||
|
# 0x0C201000
|
||||||
|
plicIntPriorityThresholdArray += tokenize(rawPlicStateFile.readline())[1:]
|
||||||
|
|
||||||
with open(outDir+'checkpoint-PLIC_INT_PRIORITY', 'w') as outFile:
|
with open(outDir+'checkpoint-PLIC_INT_PRIORITY', 'w') as outFile:
|
||||||
for word in plicIntPriorityArray:
|
for word in plicIntPriorityArray:
|
||||||
outFile.write(stripZeroes(word[2:])+'\n')
|
outFile.write(stripZeroes(word[2:])+'\n')
|
||||||
with open(outDir+'checkpoint-PLIC_INT_ENABLE', 'w') as outFile:
|
with open(outDir+'checkpoint-PLIC_INT_ENABLE', 'w') as outFile:
|
||||||
for word in plicIntEnable:
|
for word in plicIntEnableArray:
|
||||||
outFile.write(stripZeroes(word[2:]))
|
outFile.write(word+'\n')
|
||||||
with open(outDir+'checkpoint-PLIC_THRESHOLD', 'w') as outFile:
|
with open(outDir+'checkpoint-PLIC_THRESHOLD', 'w') as outFile:
|
||||||
for word in plicIntPriorityThreshold:
|
for word in plicIntPriorityThresholdArray:
|
||||||
outFile.write(stripZeroes(word[2:])+'\n')
|
outFile.write(stripZeroes(word[2:])+'\n')
|
||||||
|
|
||||||
print("Finished parsing PLIC state!")
|
print("Finished parsing PLIC state!")
|
||||||
|
@ -43,7 +43,7 @@ module csr #(parameter
|
|||||||
input logic [31:0] InstrM,
|
input logic [31:0] InstrM,
|
||||||
input logic [`XLEN-1:0] PCM, SrcAM,
|
input logic [`XLEN-1:0] PCM, SrcAM,
|
||||||
input logic CSRReadM, CSRWriteM, TrapM, MTrapM, STrapM, UTrapM, mretM, sretM,
|
input logic CSRReadM, CSRWriteM, TrapM, MTrapM, STrapM, UTrapM, mretM, sretM,
|
||||||
input logic TimerIntM, ExtIntM, SwIntM,
|
input logic TimerIntM, ExtIntM, ExtIntS, SwIntM,
|
||||||
input logic [63:0] MTIME_CLINT,
|
input logic [63:0] MTIME_CLINT,
|
||||||
input logic InstrValidM, FRegWriteM, LoadStallD,
|
input logic InstrValidM, FRegWriteM, LoadStallD,
|
||||||
input logic BPPredDirWrongM,
|
input logic BPPredDirWrongM,
|
||||||
@ -123,7 +123,7 @@ module csr #(parameter
|
|||||||
assign CSRUWriteM = CSRWriteM;
|
assign CSRUWriteM = CSRWriteM;
|
||||||
|
|
||||||
csri csri(.clk, .reset, .InstrValidNotFlushedM, .StallW, .CSRMWriteM, .CSRSWriteM,
|
csri csri(.clk, .reset, .InstrValidNotFlushedM, .StallW, .CSRMWriteM, .CSRSWriteM,
|
||||||
.CSRAdrM, .ExtIntM, .TimerIntM, .SwIntM,
|
.CSRAdrM, .ExtIntM, .ExtIntS, .TimerIntM, .SwIntM,
|
||||||
.MIDELEG_REGW, .MIP_REGW, .MIE_REGW, .SIP_REGW, .SIE_REGW, .CSRWriteValM);
|
.MIDELEG_REGW, .MIP_REGW, .MIE_REGW, .SIP_REGW, .SIE_REGW, .CSRWriteValM);
|
||||||
csrsr csrsr(.clk, .reset, .StallW,
|
csrsr csrsr(.clk, .reset, .StallW,
|
||||||
.WriteMSTATUSM, .WriteSSTATUSM,
|
.WriteMSTATUSM, .WriteSSTATUSM,
|
||||||
|
@ -41,7 +41,7 @@ module csri #(parameter
|
|||||||
input logic InstrValidNotFlushedM, StallW,
|
input logic InstrValidNotFlushedM, StallW,
|
||||||
input logic CSRMWriteM, CSRSWriteM,
|
input logic CSRMWriteM, CSRSWriteM,
|
||||||
input logic [11:0] CSRAdrM,
|
input logic [11:0] CSRAdrM,
|
||||||
input logic ExtIntM, TimerIntM, SwIntM,
|
input logic ExtIntM, ExtIntS, TimerIntM, SwIntM,
|
||||||
input logic [`XLEN-1:0] MIDELEG_REGW,
|
input logic [`XLEN-1:0] MIDELEG_REGW,
|
||||||
output logic [11:0] MIP_REGW, MIE_REGW, SIP_REGW, SIE_REGW,
|
output logic [11:0] MIP_REGW, MIE_REGW, SIP_REGW, SIE_REGW,
|
||||||
input logic [`XLEN-1:0] CSRWriteValM
|
input logic [`XLEN-1:0] CSRWriteValM
|
||||||
@ -57,8 +57,8 @@ module csri #(parameter
|
|||||||
|
|
||||||
always_comb begin
|
always_comb begin
|
||||||
IntInM = 0;
|
IntInM = 0;
|
||||||
IntInM[11] = ExtIntM;; // MEIP
|
IntInM[11] = ExtIntM; // MEIP
|
||||||
IntInM[9] = ExtIntM & MIDELEG_REGW[9]; // SEIP
|
IntInM[9] = ExtIntS | (ExtIntM & MIDELEG_REGW[9]); // SEIP
|
||||||
IntInM[7] = TimerIntM; // MTIP
|
IntInM[7] = TimerIntM; // MTIP
|
||||||
IntInM[5] = TimerIntM & MIDELEG_REGW[5]; // STIP
|
IntInM[5] = TimerIntM & MIDELEG_REGW[5]; // STIP
|
||||||
IntInM[3] = SwIntM; // MSIP
|
IntInM[3] = SwIntM; // MSIP
|
||||||
@ -82,21 +82,19 @@ module csri #(parameter
|
|||||||
assign MIP_WRITE_MASK = 12'h000;
|
assign MIP_WRITE_MASK = 12'h000;
|
||||||
assign SIP_WRITE_MASK = 12'h000;
|
assign SIP_WRITE_MASK = 12'h000;
|
||||||
end
|
end
|
||||||
always @(posedge clk) //, posedge reset) begin // *** I strongly feel that IntInM should go directly to IP_REGW -- Ben 9/7/21
|
always @(posedge clk)
|
||||||
if (reset) IP_REGW_writeable <= 10'b0;
|
if (reset) IP_REGW_writeable <= 10'b0;
|
||||||
else if (WriteMIPM) IP_REGW_writeable <= (CSRWriteValM[9:0] & MIP_WRITE_MASK[9:0]) | IntInM[9:0]; // MTIP unclearable
|
else if (WriteMIPM) IP_REGW_writeable <= (CSRWriteValM[9:0] & MIP_WRITE_MASK[9:0]) | {1'b0,IntInM[8:0]}; // MTIP unclearable
|
||||||
else if (WriteSIPM) IP_REGW_writeable <= (CSRWriteValM[9:0] & SIP_WRITE_MASK[9:0]) | IntInM[9:0]; // MTIP unclearable
|
else if (WriteSIPM) IP_REGW_writeable <= (CSRWriteValM[9:0] & SIP_WRITE_MASK[9:0]) | {1'b0,IntInM[8:0]}; // MTIP unclearable
|
||||||
// else if (WriteUIPM) IP_REGW = (CSRWriteValM & 12'hBBB) | (NextIPM & 12'h080); // MTIP unclearable
|
else IP_REGW_writeable <= IP_REGW_writeable | {1'b0, IntInM[8:0]}; // *** check this turns off interrupts properly even when MIDELEG changes
|
||||||
else IP_REGW_writeable <= IP_REGW_writeable | IntInM[9:0]; // *** check this turns off interrupts properly even when MIDELEG changes
|
always @(posedge clk)
|
||||||
always @(posedge clk) //, posedge reset) begin
|
|
||||||
if (reset) IE_REGW <= 12'b0;
|
if (reset) IE_REGW <= 12'b0;
|
||||||
else if (WriteMIEM) IE_REGW <= (CSRWriteValM[11:0] & 12'hAAA); // MIE controls M and S fields
|
else if (WriteMIEM) IE_REGW <= (CSRWriteValM[11:0] & 12'hAAA); // MIE controls M and S fields
|
||||||
else if (WriteSIEM) IE_REGW <= (CSRWriteValM[11:0] & 12'h222) | (IE_REGW & 12'h888); // only S fields
|
else if (WriteSIEM) IE_REGW <= (CSRWriteValM[11:0] & 12'h222) | (IE_REGW & 12'h888); // only S fields
|
||||||
// else if (WriteUIEM) IE_REGW = (CSRWriteValM & 12'h111) | (IE_REGW & 12'hAAA); // only U field
|
|
||||||
|
|
||||||
// restricted views of registers
|
// restricted views of registers
|
||||||
// Add MEIP read-only signal
|
// Add ExtIntM read-only signal
|
||||||
assign IP_REGW = {IntInM[11],1'b0,IP_REGW_writeable};
|
assign IP_REGW = {ExtIntM,1'b0,ExtIntS,9'b0} | {2'b0,IP_REGW_writeable};
|
||||||
|
|
||||||
// Machine Mode
|
// Machine Mode
|
||||||
assign MIP_REGW = IP_REGW;
|
assign MIP_REGW = IP_REGW;
|
||||||
|
@ -55,7 +55,7 @@ module privileged (
|
|||||||
input logic InstrMisalignedFaultM, IllegalIEUInstrFaultD, IllegalFPUInstrD,
|
input logic InstrMisalignedFaultM, IllegalIEUInstrFaultD, IllegalFPUInstrD,
|
||||||
input logic LoadMisalignedFaultM,
|
input logic LoadMisalignedFaultM,
|
||||||
input logic StoreAmoMisalignedFaultM,
|
input logic StoreAmoMisalignedFaultM,
|
||||||
input logic TimerIntM, ExtIntM, SwIntM,
|
input logic TimerIntM, ExtIntM, ExtIntS, SwIntM,
|
||||||
input logic [63:0] MTIME_CLINT,
|
input logic [63:0] MTIME_CLINT,
|
||||||
input logic [`XLEN-1:0] InstrMisalignedAdrM, IEUAdrM,
|
input logic [`XLEN-1:0] InstrMisalignedAdrM, IEUAdrM,
|
||||||
input logic [4:0] SetFflagsM,
|
input logic [4:0] SetFflagsM,
|
||||||
@ -150,7 +150,7 @@ module privileged (
|
|||||||
.StallE, .StallM, .StallW,
|
.StallE, .StallM, .StallW,
|
||||||
.InstrM, .PCM, .SrcAM,
|
.InstrM, .PCM, .SrcAM,
|
||||||
.CSRReadM, .CSRWriteM, .TrapM, .MTrapM, .STrapM, .UTrapM, .mretM, .sretM,
|
.CSRReadM, .CSRWriteM, .TrapM, .MTrapM, .STrapM, .UTrapM, .mretM, .sretM,
|
||||||
.TimerIntM, .ExtIntM, .SwIntM,
|
.TimerIntM, .ExtIntM, .ExtIntS, .SwIntM,
|
||||||
.MTIME_CLINT,
|
.MTIME_CLINT,
|
||||||
.InstrValidM, .FRegWriteM, .LoadStallD,
|
.InstrValidM, .FRegWriteM, .LoadStallD,
|
||||||
.BPPredDirWrongM, .BTBPredPCWrongM, .RASPredPCWrongM,
|
.BPPredDirWrongM, .BTBPredPCWrongM, .RASPredPCWrongM,
|
||||||
|
@ -37,6 +37,15 @@
|
|||||||
|
|
||||||
`include "wally-config.vh"
|
`include "wally-config.vh"
|
||||||
|
|
||||||
|
`define N `PLIC_NUM_SRC
|
||||||
|
// number of interrupt sources
|
||||||
|
// does not include source 0, which does not connect to anything according to spec
|
||||||
|
// up to 63 sources supported; *** in the future, allow up to 1023 sources
|
||||||
|
|
||||||
|
`define C 2
|
||||||
|
// number of conexts
|
||||||
|
// hardcoded to 2 contexts for now; *** later upgrade to arbitrary (up to 15872) contexts
|
||||||
|
|
||||||
module plic (
|
module plic (
|
||||||
input logic HCLK, HRESETn,
|
input logic HCLK, HRESETn,
|
||||||
input logic HSELPLIC,
|
input logic HSELPLIC,
|
||||||
@ -48,25 +57,26 @@ module plic (
|
|||||||
input logic UARTIntr,GPIOIntr,
|
input logic UARTIntr,GPIOIntr,
|
||||||
output logic [`XLEN-1:0] HREADPLIC,
|
output logic [`XLEN-1:0] HREADPLIC,
|
||||||
output logic HRESPPLIC, HREADYPLIC,
|
output logic HRESPPLIC, HREADYPLIC,
|
||||||
output logic ExtIntM);
|
output logic ExtIntM, ExtIntS);
|
||||||
|
|
||||||
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 [23:0] entry, entryd;
|
logic [23:0] entry, entryd;
|
||||||
logic [31:0] Din, Dout;
|
logic [31:0] Din, Dout;
|
||||||
logic [N:1] requests;
|
|
||||||
|
|
||||||
logic [2:0] intPriority[N:1];
|
// context-independent signals
|
||||||
logic [2:0] intThreshold;
|
logic [`N:1] requests;
|
||||||
logic [N:1] intPending, nextIntPending, intEn, intInProgress;
|
logic [`N:1][2:0] intPriority;
|
||||||
logic [5:0] intClaim; // ID's are 6 bits if we stay within 63 sources
|
logic [`N:1] intInProgress, intPending, nextIntPending;
|
||||||
|
|
||||||
logic [N:1] pendingArray[7:1];
|
// context-dependent signals
|
||||||
logic [7:1] pendingPGrouped;
|
logic [`C-1:0][2:0] intThreshold;
|
||||||
logic [7:1] pendingMaxP;
|
logic [`C-1:0][`N:1] intEn;
|
||||||
logic [N:1] pendingRequestsAtMaxP;
|
logic [`C-1:0][5:0] intClaim; // ID's are 6 bits if we stay within 63 sources
|
||||||
logic [7:1] threshMask;
|
logic [`C-1:0][7:1][`N:1] irqMatrix;
|
||||||
|
logic [`C-1:0][7:1] priorities_with_irqs;
|
||||||
|
logic [`C-1:0][7:1] max_priority_with_irqs;
|
||||||
|
logic [`C-1:0][`N:1] irqs_at_max_priority;
|
||||||
|
logic [`C-1:0][7:1] threshMask;
|
||||||
|
|
||||||
// =======
|
// =======
|
||||||
// AHB I/O
|
// AHB I/O
|
||||||
@ -86,8 +96,8 @@ module plic (
|
|||||||
assign Din = entryd[2] ? HWDATA[63:32] : HWDATA[31:0];
|
assign Din = entryd[2] ? HWDATA[63:32] : HWDATA[31:0];
|
||||||
assign HREADPLIC = entryd[2] ? {Dout,32'b0} : {32'b0,Dout};
|
assign HREADPLIC = entryd[2] ? {Dout,32'b0} : {32'b0,Dout};
|
||||||
end else begin // 32-bit
|
end else begin // 32-bit
|
||||||
assign Din = HWDATA[31:0];
|
|
||||||
assign HREADPLIC = Dout;
|
assign HREADPLIC = Dout;
|
||||||
|
assign Din = HWDATA[31:0];
|
||||||
end
|
end
|
||||||
|
|
||||||
// ==================
|
// ==================
|
||||||
@ -96,43 +106,56 @@ module plic (
|
|||||||
always @(posedge HCLK,negedge HRESETn) begin
|
always @(posedge HCLK,negedge HRESETn) begin
|
||||||
// resetting
|
// resetting
|
||||||
if (~HRESETn) begin
|
if (~HRESETn) begin
|
||||||
intPriority <= #1 '{default:3'b0};
|
intPriority <= #1 {`N{3'b0}};
|
||||||
intEn <= #1 {N{1'b0}};
|
intEn <= #1 {2{`N'b0}};
|
||||||
intThreshold <= #1 3'b0;
|
intThreshold <= #1 {2{3'b0}};
|
||||||
intInProgress <= #1 {N{1'b0}};
|
intInProgress <= #1 `N'b0;
|
||||||
// writing
|
// writing
|
||||||
end else begin
|
end else begin
|
||||||
if (memwrite)
|
if (memwrite)
|
||||||
casez(entryd)
|
casez(entryd)
|
||||||
24'h0000??: 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 // *** switch to a generate for loop so as to deprecate PLIC_NUM_SRC_LT_32 and allow up to 1023 sources
|
||||||
24'h002000: intEn[N:1] <= #1 Din[N:1];
|
24'h002000: intEn[0][`N:1] <= #1 Din[`N:1];
|
||||||
|
24'h002080: intEn[1][`N:1] <= #1 Din[`N:1];
|
||||||
`endif
|
`endif
|
||||||
`ifndef PLIC_NUM_SRC_LT_32
|
`ifndef PLIC_NUM_SRC_LT_32
|
||||||
24'h002000: intEn[31:1] <= #1 Din[31:1];
|
24'h002000: intEn[0][31:1] <= #1 Din[31:1];
|
||||||
24'h002004: intEn[N:32] <= #1 Din[31:0];
|
24'h002004: intEn[0][`N:32] <= #1 Din[31:0];
|
||||||
|
24'h002080: intEn[1][31:1] <= #1 Din[31:1];
|
||||||
|
24'h002084: intEn[1][`N:32] <= #1 Din[31:0];
|
||||||
`endif
|
`endif
|
||||||
24'h200000: intThreshold[2:0] <= #1 Din[2:0];
|
24'h200000: intThreshold[0] <= #1 Din[2:0];
|
||||||
24'h200004: intInProgress <= #1 intInProgress & ~(`PLIC_NUM_SRC'b1 << (Din[5:0]-1)); // lower "InProgress" to signify completion
|
24'h200004: intInProgress <= #1 intInProgress & ~(`N'b1 << (Din[5:0]-1)); // lower "InProgress" to signify completion
|
||||||
|
24'h201000: intThreshold[1] <= #1 Din[2:0];
|
||||||
|
24'h201004: intInProgress <= #1 intInProgress & ~(`N'b1 << (Din[5:0]-1)); // lower "InProgress" to signify completion
|
||||||
endcase
|
endcase
|
||||||
// reading
|
// reading
|
||||||
if (memread)
|
if (memread)
|
||||||
casez(entry)
|
casez(entry)
|
||||||
24'h0000??: Dout <= #1 {29'b0,intPriority[entry[7:2]]};
|
24'h0000??: Dout <= #1 {29'b0,intPriority[entry[7:2]]};
|
||||||
`ifdef PLIC_NUM_SRC_LT_32
|
`ifdef PLIC_NUM_SRC_LT_32
|
||||||
24'h001000: Dout <= #1 {{(31-N){1'b0}},intPending[N:1],1'b0};
|
24'h001000: Dout <= #1 {{(31-`N){1'b0}},intPending,1'b0};
|
||||||
24'h002000: Dout <= #1 {{(31-N){1'b0}},intEn[N:1],1'b0};
|
24'h002000: Dout <= #1 {{(31-`N){1'b0}},intEn[0],1'b0};
|
||||||
|
24'h002080: Dout <= #1 {{(31-`N){1'b0}},intEn[1],1'b0};
|
||||||
`endif
|
`endif
|
||||||
`ifndef PLIC_NUM_SRC_LT_32
|
`ifndef PLIC_NUM_SRC_LT_32
|
||||||
24'h001000: Dout <= #1 {intPending[31:1],1'b0};
|
24'h001000: Dout <= #1 {intPending[31:1],1'b0};
|
||||||
24'h001004: Dout <= #1 {{(63-N){1'b0}},intPending[N:32]};
|
24'h001004: Dout <= #1 {{(63-`N){1'b0}},intPending[`N:32]};
|
||||||
24'h002000: Dout <= #1 {intEn[31:1],1'b0};
|
24'h002000: Dout <= #1 {intEn[0][31:1],1'b0};
|
||||||
24'h002004: Dout <= #1 {{(63-N){1'b0}},intEn[N:32]};
|
24'h002004: Dout <= #1 {{(63-`N){1'b0}},intEn[0][`N:32]};
|
||||||
|
24'h002080: Dout <= #1 {intEn[0][31:1],1'b0};
|
||||||
|
24'h002084: Dout <= #1 {{(63-`N){1'b0}},intEn[1][`N:32]};
|
||||||
`endif
|
`endif
|
||||||
24'h200000: Dout <= #1 {29'b0,intThreshold[2:0]};
|
24'h200000: Dout <= #1 {29'b0,intThreshold[0]};
|
||||||
24'h200004: begin
|
24'h200004: begin
|
||||||
Dout <= #1 {26'b0,intClaim};
|
Dout <= #1 {26'b0,intClaim[0]};
|
||||||
intInProgress <= #1 intInProgress | (`PLIC_NUM_SRC'b1 << (intClaim-1)); // claimed requests are currently in progress of being serviced until they are completed
|
intInProgress <= #1 intInProgress | (`N'b1 << (intClaim[0]-1)); // claimed requests are currently in progress of being serviced until they are completed
|
||||||
|
end
|
||||||
|
24'h201000: Dout <= #1 {29'b0,intThreshold[1]};
|
||||||
|
24'h201004: begin
|
||||||
|
Dout <= #1 {26'b0,intClaim[1]};
|
||||||
|
intInProgress <= #1 intInProgress | (`N'b1 << (intClaim[1]-1)); // claimed requests are currently in progress of being serviced until they are completed
|
||||||
end
|
end
|
||||||
default: Dout <= #1 32'h0; // invalid access
|
default: Dout <= #1 32'h0; // invalid access
|
||||||
endcase
|
endcase
|
||||||
@ -143,7 +166,7 @@ module plic (
|
|||||||
|
|
||||||
// connect sources to requests
|
// connect sources to requests
|
||||||
always_comb begin
|
always_comb begin
|
||||||
requests = {N{1'b0}};
|
requests = `N'b0;
|
||||||
`ifdef PLIC_GPIO_ID
|
`ifdef PLIC_GPIO_ID
|
||||||
requests[`PLIC_GPIO_ID] = GPIOIntr;
|
requests[`PLIC_GPIO_ID] = GPIOIntr;
|
||||||
`endif
|
`endif
|
||||||
@ -152,66 +175,88 @@ module plic (
|
|||||||
`endif
|
`endif
|
||||||
end
|
end
|
||||||
|
|
||||||
// pending updates
|
// pending interrupt requests
|
||||||
// *** verify that this matches the expectations of the things that make requests (in terms of timing, edge-triggered vs level-triggered)
|
assign nextIntPending =
|
||||||
assign nextIntPending = (intPending | (requests & ~intInProgress)) & // requests should raise intPending except when their service routine is already in progress
|
(intPending | // existing pending requests
|
||||||
~({N{((entry == 24'h200004) & memread)}} << (intClaim-1)); // clear pending bit when claim register is read
|
(requests & ~intInProgress)) & // assert new requests (if they aren't already being serviced)
|
||||||
flopr #(N) intPendingFlop(HCLK,~HRESETn,nextIntPending,intPending);
|
~({`N{((entry == 24'h200004) & memread)}} << (intClaim[0]-1)) & // deassert requests that just completed
|
||||||
|
~({`N{((entry == 24'h201004) & memread)}} << (intClaim[1]-1));
|
||||||
|
flopr #(`N) intPendingFlop(HCLK,~HRESETn,nextIntPending,intPending);
|
||||||
|
|
||||||
// pending array - indexed by priority_lvl x source_ID
|
// context-dependent signals
|
||||||
genvar i, j;
|
genvar ctx;
|
||||||
for (j=1; j<=7; j++) begin: pending
|
for (ctx=0; ctx<`C; ctx++) begin
|
||||||
for (i=1; i<=N; i=i+1) begin: pendingbit
|
// request matrix
|
||||||
assign pendingArray[j][i] = (intPriority[i]==j) & intEn[i] & intPending[i];
|
// priority level (rows) X source ID (columns)
|
||||||
|
//
|
||||||
|
// irqMatrix[ctx][pri][src] is high if source <src>
|
||||||
|
// has priority level <pri> and has an "active" interrupt request
|
||||||
|
// ("active" meaning it is enabled in context <ctx> and is pending)
|
||||||
|
genvar src, pri;
|
||||||
|
for (pri=1; pri<=7; pri++) begin
|
||||||
|
for (src=1; src<=`N; src++) begin
|
||||||
|
assign irqMatrix[ctx][pri][src] = (intPriority[src]==pri) & intPending[src] & intEn[ctx][src];
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
// pending array, except grouped by priority
|
|
||||||
assign pendingPGrouped[7:1] = {|pendingArray[7],
|
|
||||||
|pendingArray[6],
|
|
||||||
|pendingArray[5],
|
|
||||||
|pendingArray[4],
|
|
||||||
|pendingArray[3],
|
|
||||||
|pendingArray[2],
|
|
||||||
|pendingArray[1]};
|
|
||||||
//assign pendingPGrouped = pendingArray.or;
|
|
||||||
|
|
||||||
// pendingPGrouped, except only topmost priority is active
|
// which prority levels have one or more active requests?
|
||||||
assign pendingMaxP[7:1] = {pendingPGrouped[7],
|
assign priorities_with_irqs[ctx][7:1] = {
|
||||||
pendingPGrouped[6] & ~|pendingPGrouped[7],
|
|irqMatrix[ctx][7],
|
||||||
pendingPGrouped[5] & ~|pendingPGrouped[7:6],
|
|irqMatrix[ctx][6],
|
||||||
pendingPGrouped[4] & ~|pendingPGrouped[7:5],
|
|irqMatrix[ctx][5],
|
||||||
pendingPGrouped[3] & ~|pendingPGrouped[7:4],
|
|irqMatrix[ctx][4],
|
||||||
pendingPGrouped[2] & ~|pendingPGrouped[7:3],
|
|irqMatrix[ctx][3],
|
||||||
pendingPGrouped[1] & ~|pendingPGrouped[7:2]};
|
|irqMatrix[ctx][2],
|
||||||
// select the pending requests at that priority
|
|irqMatrix[ctx][1]
|
||||||
assign pendingRequestsAtMaxP[N:1] = ({N{pendingMaxP[7]}} & pendingArray[7])
|
};
|
||||||
| ({N{pendingMaxP[6]}} & pendingArray[6])
|
|
||||||
| ({N{pendingMaxP[5]}} & pendingArray[5])
|
// get the highest priority level that has active requests
|
||||||
| ({N{pendingMaxP[4]}} & pendingArray[4])
|
assign max_priority_with_irqs[ctx][7:1] = {
|
||||||
| ({N{pendingMaxP[3]}} & pendingArray[3])
|
priorities_with_irqs[ctx][7],
|
||||||
| ({N{pendingMaxP[2]}} & pendingArray[2])
|
priorities_with_irqs[ctx][6] & ~|priorities_with_irqs[ctx][7],
|
||||||
| ({N{pendingMaxP[1]}} & pendingArray[1]);
|
priorities_with_irqs[ctx][5] & ~|priorities_with_irqs[ctx][7:6],
|
||||||
// find the lowest ID amongst active interrupts at the highest priority
|
priorities_with_irqs[ctx][4] & ~|priorities_with_irqs[ctx][7:5],
|
||||||
logic [5:0] k;
|
priorities_with_irqs[ctx][3] & ~|priorities_with_irqs[ctx][7:4],
|
||||||
|
priorities_with_irqs[ctx][2] & ~|priorities_with_irqs[ctx][7:3],
|
||||||
|
priorities_with_irqs[ctx][1] & ~|priorities_with_irqs[ctx][7:2]
|
||||||
|
};
|
||||||
|
|
||||||
|
// of the sources at the highest priority level that has active requests,
|
||||||
|
// which sources have active requests?
|
||||||
|
assign irqs_at_max_priority[ctx][`N:1] =
|
||||||
|
({`N{max_priority_with_irqs[ctx][7]}} & irqMatrix[ctx][7]) |
|
||||||
|
({`N{max_priority_with_irqs[ctx][6]}} & irqMatrix[ctx][6]) |
|
||||||
|
({`N{max_priority_with_irqs[ctx][5]}} & irqMatrix[ctx][5]) |
|
||||||
|
({`N{max_priority_with_irqs[ctx][4]}} & irqMatrix[ctx][4]) |
|
||||||
|
({`N{max_priority_with_irqs[ctx][3]}} & irqMatrix[ctx][3]) |
|
||||||
|
({`N{max_priority_with_irqs[ctx][2]}} & irqMatrix[ctx][2]) |
|
||||||
|
({`N{max_priority_with_irqs[ctx][1]}} & irqMatrix[ctx][1]);
|
||||||
|
|
||||||
|
// of the sources at the highest priority level that has active requests,
|
||||||
|
// choose the source with the lowest source ID to be the most urgent
|
||||||
|
// and set intClaim to the source ID of the most urgent active request
|
||||||
|
integer k;
|
||||||
always_comb begin
|
always_comb begin
|
||||||
intClaim = 6'b0;
|
intClaim[ctx] = 6'b0;
|
||||||
for (k=N; k>0; k=k-1) begin
|
for (k=`N; k>0; k--) begin
|
||||||
if (pendingRequestsAtMaxP[k]) intClaim = k;
|
if (irqs_at_max_priority[ctx][k]) intClaim[ctx] = k[5:0];
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
// create threshold mask
|
// create threshold mask
|
||||||
always_comb begin
|
always_comb begin
|
||||||
threshMask[7] = (intThreshold != 7);
|
threshMask[ctx][7] = (intThreshold[ctx] != 7);
|
||||||
threshMask[6] = (intThreshold != 6) & threshMask[7];
|
threshMask[ctx][6] = (intThreshold[ctx] != 6) & threshMask[ctx][7];
|
||||||
threshMask[5] = (intThreshold != 5) & threshMask[6];
|
threshMask[ctx][5] = (intThreshold[ctx] != 5) & threshMask[ctx][6];
|
||||||
threshMask[4] = (intThreshold != 4) & threshMask[5];
|
threshMask[ctx][4] = (intThreshold[ctx] != 4) & threshMask[ctx][5];
|
||||||
threshMask[3] = (intThreshold != 3) & threshMask[4];
|
threshMask[ctx][3] = (intThreshold[ctx] != 3) & threshMask[ctx][4];
|
||||||
threshMask[2] = (intThreshold != 2) & threshMask[3];
|
threshMask[ctx][2] = (intThreshold[ctx] != 2) & threshMask[ctx][3];
|
||||||
threshMask[1] = (intThreshold != 1) & threshMask[2];
|
threshMask[ctx][1] = (intThreshold[ctx] != 1) & threshMask[ctx][2];
|
||||||
end
|
end
|
||||||
// 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);
|
end
|
||||||
|
assign ExtIntM = |(threshMask[0] & priorities_with_irqs[0]);
|
||||||
|
assign ExtIntS = |(threshMask[1] & priorities_with_irqs[1]);
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ module uncore (
|
|||||||
input logic [3:0] HSIZED,
|
input logic [3:0] HSIZED,
|
||||||
input logic HWRITED,
|
input logic HWRITED,
|
||||||
// peripheral pins
|
// peripheral pins
|
||||||
output logic TimerIntM, SwIntM, ExtIntM,
|
output logic TimerIntM, SwIntM, ExtIntM, ExtIntS,
|
||||||
input logic [31:0] GPIOPinsIn,
|
input logic [31:0] GPIOPinsIn,
|
||||||
output logic [31:0] GPIOPinsOut, GPIOPinsEn,
|
output logic [31:0] GPIOPinsOut, GPIOPinsEn,
|
||||||
input logic UARTSin,
|
input logic UARTSin,
|
||||||
@ -133,9 +133,10 @@ module uncore (
|
|||||||
.HWRITE, .HREADY, .HTRANS, .HWDATA,
|
.HWRITE, .HREADY, .HTRANS, .HWDATA,
|
||||||
.UARTIntr, .GPIOIntr,
|
.UARTIntr, .GPIOIntr,
|
||||||
.HREADPLIC, .HRESPPLIC, .HREADYPLIC,
|
.HREADPLIC, .HRESPPLIC, .HREADYPLIC,
|
||||||
.ExtIntM);
|
.ExtIntM, .ExtIntS);
|
||||||
end else begin : plic
|
end else begin : plic
|
||||||
assign ExtIntM = 0;
|
assign ExtIntM = 0;
|
||||||
|
assign ExtIntS = 0;
|
||||||
end
|
end
|
||||||
if (`GPIO_SUPPORTED == 1) begin : gpio
|
if (`GPIO_SUPPORTED == 1) begin : gpio
|
||||||
gpio gpio(
|
gpio gpio(
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
module wallypipelinedcore (
|
module wallypipelinedcore (
|
||||||
input logic clk, reset,
|
input logic clk, reset,
|
||||||
// Privileged
|
// Privileged
|
||||||
input logic TimerIntM, ExtIntM, SwIntM,
|
input logic TimerIntM, ExtIntM, ExtIntS, SwIntM,
|
||||||
input logic [63:0] MTIME_CLINT,
|
input logic [63:0] MTIME_CLINT,
|
||||||
// Bus Interface
|
// Bus Interface
|
||||||
input logic [`AHBW-1:0] HRDATA,
|
input logic [`AHBW-1:0] HRDATA,
|
||||||
@ -331,7 +331,7 @@ module wallypipelinedcore (
|
|||||||
.InstrPageFaultF, .LoadPageFaultM, .StoreAmoPageFaultM,
|
.InstrPageFaultF, .LoadPageFaultM, .StoreAmoPageFaultM,
|
||||||
.InstrMisalignedFaultM, .IllegalIEUInstrFaultD, .IllegalFPUInstrD,
|
.InstrMisalignedFaultM, .IllegalIEUInstrFaultD, .IllegalFPUInstrD,
|
||||||
.LoadMisalignedFaultM, .StoreAmoMisalignedFaultM,
|
.LoadMisalignedFaultM, .StoreAmoMisalignedFaultM,
|
||||||
.TimerIntM, .ExtIntM, .SwIntM,
|
.TimerIntM, .ExtIntM, .ExtIntS, .SwIntM,
|
||||||
.MTIME_CLINT,
|
.MTIME_CLINT,
|
||||||
.InstrMisalignedAdrM, .IEUAdrM,
|
.InstrMisalignedAdrM, .IEUAdrM,
|
||||||
.SetFflagsM,
|
.SetFflagsM,
|
||||||
|
@ -74,7 +74,7 @@ module wallypipelinedsoc (
|
|||||||
logic HRESP;
|
logic HRESP;
|
||||||
logic TimerIntM, SwIntM; // from CLINT
|
logic TimerIntM, SwIntM; // from CLINT
|
||||||
logic [63:0] MTIME_CLINT; // from CLINT to CSRs
|
logic [63:0] MTIME_CLINT; // from CLINT to CSRs
|
||||||
logic ExtIntM; // from PLIC
|
logic ExtIntM,ExtIntS; // from PLIC
|
||||||
logic [2:0] HADDRD;
|
logic [2:0] HADDRD;
|
||||||
logic [3:0] HSIZED;
|
logic [3:0] HSIZED;
|
||||||
logic HWRITED;
|
logic HWRITED;
|
||||||
@ -84,7 +84,7 @@ module wallypipelinedsoc (
|
|||||||
|
|
||||||
// instantiate processor and memories
|
// instantiate processor and memories
|
||||||
wallypipelinedcore core(.clk, .reset,
|
wallypipelinedcore core(.clk, .reset,
|
||||||
.TimerIntM, .ExtIntM, .SwIntM,
|
.TimerIntM, .ExtIntM, .ExtIntS, .SwIntM,
|
||||||
.MTIME_CLINT,
|
.MTIME_CLINT,
|
||||||
.HRDATA, .HREADY, .HRESP, .HCLK, .HRESETn, .HADDR, .HWDATA,
|
.HRDATA, .HREADY, .HRESP, .HCLK, .HRESETn, .HADDR, .HWDATA,
|
||||||
.HWRITE, .HSIZE, .HBURST, .HPROT, .HTRANS, .HMASTLOCK,
|
.HWRITE, .HSIZE, .HBURST, .HPROT, .HTRANS, .HMASTLOCK,
|
||||||
@ -94,7 +94,7 @@ module wallypipelinedsoc (
|
|||||||
uncore uncore(.HCLK, .HRESETn, .TIMECLK,
|
uncore uncore(.HCLK, .HRESETn, .TIMECLK,
|
||||||
.HADDR, .HWDATA, .HWRITE, .HSIZE, .HBURST, .HPROT, .HTRANS, .HMASTLOCK, .HRDATAEXT,
|
.HADDR, .HWDATA, .HWRITE, .HSIZE, .HBURST, .HPROT, .HTRANS, .HMASTLOCK, .HRDATAEXT,
|
||||||
.HREADYEXT, .HRESPEXT, .HRDATA, .HREADY, .HRESP, .HADDRD, .HSIZED, .HWRITED,
|
.HREADYEXT, .HRESPEXT, .HRDATA, .HREADY, .HRESP, .HADDRD, .HSIZED, .HWRITED,
|
||||||
.TimerIntM, .SwIntM, .ExtIntM, .GPIOPinsIn, .GPIOPinsOut, .GPIOPinsEn, .UARTSin, .UARTSout, .MTIME_CLINT,
|
.TimerIntM, .SwIntM, .ExtIntM, .ExtIntS, .GPIOPinsIn, .GPIOPinsOut, .GPIOPinsEn, .UARTSin, .UARTSout, .MTIME_CLINT,
|
||||||
.HSELEXT,
|
.HSELEXT,
|
||||||
.SDCCmdOut, .SDCCmdOE, .SDCCmdIn, .SDCDatIn, .SDCCLK
|
.SDCCmdOut, .SDCCmdOE, .SDCCmdIn, .SDCDatIn, .SDCCLK
|
||||||
|
|
||||||
|
@ -334,8 +334,8 @@ module testbench;
|
|||||||
//`INIT_CHECKPOINT_VAL(UART_MSR, [7:0]);
|
//`INIT_CHECKPOINT_VAL(UART_MSR, [7:0]);
|
||||||
`INIT_CHECKPOINT_VAL(UART_SCR, [7:0]);
|
`INIT_CHECKPOINT_VAL(UART_SCR, [7:0]);
|
||||||
`INIT_CHECKPOINT_SIMPLE_ARRAY(PLIC_INT_PRIORITY, [2:0],`PLIC_NUM_SRC,1);
|
`INIT_CHECKPOINT_SIMPLE_ARRAY(PLIC_INT_PRIORITY, [2:0],`PLIC_NUM_SRC,1);
|
||||||
`INIT_CHECKPOINT_VAL(PLIC_INT_ENABLE, [`PLIC_NUM_SRC:1]);
|
`INIT_CHECKPOINT_SIMPLE_ARRAY(PLIC_INT_ENABLE, [`PLIC_NUM_SRC:1],1,0);
|
||||||
`INIT_CHECKPOINT_VAL(PLIC_THRESHOLD, [2:0]);
|
`INIT_CHECKPOINT_SIMPLE_ARRAY(PLIC_THRESHOLD, [2:0],1,0);
|
||||||
|
|
||||||
integer memFile;
|
integer memFile;
|
||||||
integer readResult;
|
integer readResult;
|
||||||
|
Loading…
Reference in New Issue
Block a user