Commit 7c34a169 authored by Guillem's avatar Guillem
Browse files

WIP: handle undriven and bugfixes

parent 7650dcdd
......@@ -79,7 +79,7 @@
localparam BASE_QUOTA_INTR = END_OVERFLOW_INTR + 1,
// mask feature
// QUOTA_INTR_MASK_REGS equivalentto to $ceil(N_COUNTERS/REG_WIDTH)
localparam BASE_QUOTA_MASK = BASE_OVERFLOW_INTR,
localparam BASE_QUOTA_MASK = BASE_QUOTA_INTR,
localparam N_QUOTA_MASK_REGS = ((N_COUNTERS-1)/REG_WIDTH+1),
localparam END_QUOTA_MASK = BASE_QUOTA_MASK + N_QUOTA_MASK_REGS -1,
// Available quota aka quota limit
......@@ -151,8 +151,8 @@
input wire rstn_i,
// Input/output wire from registers of the wrapper to PMU_raw internal
// registers
input wire [REG_WIDTH-1:0] regs_i [0:TOTAL_NREGS-1],
output wire [REG_WIDTH-1:0] regs_o [0:TOTAL_NREGS-1],
input logic [REG_WIDTH-1:0] regs_i [0:TOTAL_NREGS-1],
output logic [REG_WIDTH-1:0] regs_o [0:TOTAL_NREGS-1],
// Wrapper writte enable, prevents slaves to write in to registers and
// uploads the content with external values
input wire wrapper_we_i,
......@@ -160,7 +160,7 @@
input wire [N_COUNTERS-1:0] events_i,
//interruption rises when one of the counters overflows
output wire intr_overflow_o,
//interruption rises when overal events quota is exceeded
//interruption rises when overall events quota is exceeded
output wire intr_quota_o,
// MCCU interruption for exceeded quota. One signal per core
output wire [MCCU_N_CORES-1:0] intr_MCCU_o,
......@@ -194,8 +194,8 @@
end
assign en_i = regs_i [BASE_CFG][0];
assign softrst_i = regs_i [BASE_CFG][1];
//Send content to wrapper
assign regs_o[BASE_CFG] = cfg_reg;
// Register never set by PMU, only written by master
assign regs_o[BASE_CFG:END_CFG] = regs_i[BASE_CFG:END_CFG];
//---- Counter registers
genvar x;
......@@ -208,14 +208,23 @@
//---- Overflow interruption registers
generate
for(x=0;x<N_OVERFLOW_MASK_REGS;x++) begin
assign overflow_intr_mask_i[x] = (rstn_i == 1'b0)? '{default:0} :regs_i [x+BASE_OVERFLOW_MASK][N_COUNTERS-1:0];
assign overflow_intr_mask_i[x] = (rstn_i == 1'b0)? {N_COUNTERS{1'b0}} :regs_i [x+BASE_OVERFLOW_MASK][N_COUNTERS-1:0];
end
for(x=BASE_OVERFLOW_VECT;x<=END_OVERFLOW_VECT;x++) begin
assign regs_o [x] = (rstn_i == 1'b0)? '{default:0} : REG_WIDTH'(overflow_intr_vect_o[x-BASE_OVERFLOW_VECT]);
assign regs_o [x] = (rstn_i == 1'b0)? {REG_WIDTH{1'b0}} : REG_WIDTH'(overflow_intr_vect_o[x-BASE_OVERFLOW_VECT]);
end
endgenerate
// Register never set by PMU, only written by master
assign regs_o[BASE_OVERFLOW_MASK:END_OVERFLOW_MASK] = regs_i[BASE_OVERFLOW_MASK:END_OVERFLOW_MASK];
//---- Quota interruption registers
// Register never set by PMU, only written by master
assign regs_o[BASE_QUOTA_MASK:END_QUOTA_MASK] = regs_i[BASE_QUOTA_MASK:END_QUOTA_MASK];
assign regs_o[BASE_QUOTA_LIMIT:END_QUOTA_LIMIT] = regs_i[BASE_QUOTA_LIMIT:END_QUOTA_LIMIT];
//---- MCCU registers
// Register never set by PMU, only written by master
assign regs_o[BASE_MCCU_CFG:END_MCCU_CFG] = regs_i[BASE_MCCU_CFG:END_MCCU_CFG];
assign regs_o[BASE_MCCU_LIMITS:END_MCCU_LIMITS] = regs_i[BASE_MCCU_LIMITS:END_MCCU_LIMITS];
assign regs_o[BASE_MCCU_WEIGHTS:END_MCCU_WEIGHTS] = regs_i[BASE_MCCU_WEIGHTS:END_MCCU_WEIGHTS];
//---- Request Duration Counter (RDC) registers
//----------------------------------------------
......@@ -369,7 +378,8 @@
assign regs_o[BASE_RDC_VECT][5:4] = interruption_rdc_o [2] ;
//core_3
assign regs_o[BASE_RDC_VECT][7:6] = interruption_rdc_o [3] ;
//spare bits on RDC_VECT
assign regs_o[BASE_RDC_VECT][REG_WIDTH-1:8] = '{default:0} ;
//TODO: A dedicated configuration register may be required for RDC, for
//now it is shared with MCCU
wire RDC_softrst;
......
......@@ -23,14 +23,25 @@
(
parameter haddr = 0,
parameter hmask = 0,
// Total amount of registers
parameter integer N_REGS = 10,
// Width of registers data bus
parameter integer REG_WIDTH = 32,
//haddr width
localparam integer HADDR_WIDTH = 32,
//hdata width
localparam integer HDATA_WIDTH = 32
localparam integer HDATA_WIDTH = 32,
//Required for MCCU interrupts
// -- PMU specific parameters
// Cores connected to MCCU
localparam MCCU_N_CORES = 4,
// Total amount of registers
parameter integer N_REGS = 26,
// Number of configuration registers
localparam PMU_CFG = 1,
// Number of counters
localparam PMU_COUNTERS = 9,
//TODO: for now it is hardcoded but this may be calculated given the
//features, n_cores and N_events in the future
localparam PMU_TOTAL_REGS = N_REGS
)
(
input wire rstn_i,
......@@ -61,8 +72,18 @@
// response type
output wire [1:0] hresp_o,
// read data bus
output wire [HDATA_WIDTH-1:0] hrdata_o
);
output wire [HDATA_WIDTH-1:0] hrdata_o,
// -- PMU specific signales
input wire [PMU_COUNTERS-1:0] events_i,
//interruption rises when one of the counters overflows
output wire intr_overflow_o,
//interruption rises when overal events quota is exceeded
output wire intr_quota_o,
// MCCU interruption for exceeded quota. One signal per core
output wire [MCCU_N_CORES-1:0] intr_MCCU_o,
// RDC (Request Duration Counter) interruption for exceeded quota
output wire intr_RDC_o
);
//----------------------------------------------
//------------- Local parameters
//----------------------------------------------
......@@ -115,7 +136,7 @@ localparam TRANSFER_ERROR_RESP_2CYCLE = 2'b11;
var struct packed{
logic select;
logic write;
logic master_ready;
// logic master_ready;
logic [HADDR_WIDTH-1:0] master_addr;
} address_phase;
......@@ -247,29 +268,27 @@ end
//----------------------------------------------
//------------- PMU_raw instance
//----------------------------------------------
localparam PMU_CFG = 1;
localparam PMU_COUNTERS = 9;
localparam PMU_TOTAL_REGS = PMU_COUNTERS + PMU_CFG;
//assert(PMU_TOTAL_REGS == N_REGS);
wire [REG_WIDTH-1:0] pmu_regs_int [0:PMU_TOTAL_REGS-1];
wire [REG_WIDTH-1:0] pmu_regs_int [0:N_REGS-1];
wire ahb_write_req;
assign ahb_write_req = address_phase.write && address_phase.select;
PMU_raw #(
.REG_WIDTH(REG_WIDTH),
.N_COUNTERS(PMU_COUNTERS),
.N_CONF_REGS(PMU_CFG),
.OVERFLOW(0), //Yes/No
.QUOTA(0), //Yes/No
.MCCU(0), //Yes/No
.N_CORES(1)
.N_CONF_REGS(PMU_CFG)
)inst_pmu_raw (
.clk_i(clk_i),
.rstn_i(rstn_i),
.regs_i(slv_reg_D),
.regs_i(slv_reg_Q),
.regs_o(pmu_regs_int),
.wrapper_we_i(ahb_write_req),
//TODO connect real events
.events_i({PMU_COUNTERS{1'b1}})
//on pourpose .name connections
.events_i,
.intr_overflow_o,
.intr_quota_o,
.intr_MCCU_o,
.intr_RDC_o
);
//----------------------------------------------
......
......@@ -105,7 +105,7 @@ module PMU_quota #
//State n = Add counter n + Suman_int
//State 0 = Reset suma_int
// ...
localparam n_states = $clog2(N_COUNTERS+1);
localparam n_states =$clog2(N_COUNTERS+1);
reg [n_states-1:0] state_int;
always_ff @(posedge clk_i, negedge rstn_i) begin
integer i;
......@@ -114,7 +114,7 @@ module PMU_quota #
end else if(softrst_i || new_mask) begin
state_int <={n_states{1'b0}};
end else begin
state_int <= state_int + 1 ;
state_int <= state_int + 1;
end
end
......@@ -139,9 +139,24 @@ module PMU_quota #
end
end
//Check if quota is exceeded and generate interrupt
//Hold the state of the interruption
reg hold_intr_quota;
always_ff @(posedge clk_i, negedge rstn_i) begin
if(rstn_i == 1'b0 ) begin
hold_intr_quota <= 1'b0;
end else begin
if(softrst_i) begin
hold_intr_quota <= 1'b0;
end else begin
hold_intr_quota <= hold_intr_quota + intr_quota_o;
end
end
end
//Check if quota is exceeded and generate interrupt or interrupt has been
//previously triggered and never reseted
assign intr_quota_o = (suma_int > quota_limit_i )
? 1'b1 : 1'b0;
? 1'b1 : hold_intr_quota;
////////////////////////////////////////////////////////////////////////////////
//
......@@ -149,6 +164,47 @@ module PMU_quota #
//
////////////////////////////////////////////////////////////////////////////////
`ifdef FORMAL
//auxiliar registers
reg f_past_valid ;
initial f_past_valid = 1'b0;
//Set f_past_valid after first clock cycle
always@( posedge clk_i )
f_past_valid <= 1'b1;
//assume that if f_past is not valid you have to reset
always @(*) begin
if(0 == f_past_valid) begin
assume(0 == rstn_i);
end
end
default clocking @(posedge clk_i); endclocking
// Set quotalimit stable and trigger the interrupt
cover property (((quota_limit_i==5)[*5] |-> (intr_quota_o==1)));
// Set all the the events in the mask to one and keep it stable
cover property ((quota_mask_i== {N_COUNTERS{1'b1}})[*5] |-> (intr_quota_o==1));
// Roll over the max value of suma_int
cover property (($past(suma_int)=={max_width{1'b1}})
&&(rstn_i == 1) &&(softrst_i == 0)
&& (new_mask==0)[*(2**n_states)+2] |-> (intr_quota_o==1)
);
// Count up, count 0 and count up again. Interrupt shall be stable
cover property (
($past(suma_int,1)=={max_width{1'b1}})
&&($past(suma_int,2)=={max_width{1'b0}})
&&($past(suma_int,3)=={max_width{1'b1}})
&&(rstn_i == 1) &&(softrst_i == 0)
);
// The interruption can't fall once it is risen unless the unit is
// softreset
assert property ($rose(intr_quota_o) |-> ($past(softrst_i)||$past(rstn_i)));
// The interruption shall be high eventually
assert property (##[0:$] intr_quota_o );
// use all inputs. Roll over all the states of the addition once before
// trigger an interrupt
//TODO
`endif
endmodule
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment