Skip to content

Commit 08da416

Browse files
committed
Modified ISS to align timing model with the rv32_cpu softcore Verilog implementation.
1 parent 70ffa74 commit 08da416

File tree

5 files changed

+53
-10
lines changed

5 files changed

+53
-10
lines changed

iss/src/cpurv32i.cpp

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -167,29 +167,37 @@ int parse_args(int argc, char** argv, rv32i_cfg_s &cfg)
167167
//
168168
int ext_mem_access(const uint32_t byte_addr, uint32_t& data, const int type, const rv32i_time_t time)
169169
{
170+
// By default, the processed variable indicates that this callback did not
171+
// process the access (a negatiave value). Otherwise it is the additional
172+
// access wait states (0 upwards). In this model, writes have no wait states,
173+
// whilst reads have 2 wait states.
170174
int processed = RV32I_EXT_MEM_NOT_PROCESSED;
171175

172-
// If not interrupt address, access memory model
176+
// If writing UART TX address, print character
173177
if (byte_addr == UART_TX_ADDR && type == MEM_WR_ACCESS_BYTE)
174178
{
175-
processed = 1;
179+
processed = 0;
176180
putchar(data & 0xff);
177181
}
182+
// If not interrupt address, access memory model
178183
else if (byte_addr != INT_ADDR)
179184
{
180185
uint32_t addr = byte_addr;
181-
processed = 1;
186+
processed = 0;
182187

183188
switch (type & MEM_NOT_DBG_MASK)
184189
{
185190
case MEM_RD_ACCESS_BYTE:
186191
data = ReadRamByte(addr, 0);
192+
processed = 2;
187193
break;
188194
case MEM_RD_ACCESS_HWORD:
189195
data = ReadRamHWord(addr, true, 0);
196+
processed = 2;
190197
break;
191-
case MEM_RD_ACCESS_INSTR:
192198
case MEM_RD_ACCESS_WORD:
199+
processed = 2;
200+
case MEM_RD_ACCESS_INSTR:
193201
data = ReadRamWord(addr, true, 0);
194202
break;
195203
case MEM_WR_ACCESS_BYTE:
@@ -210,7 +218,7 @@ int ext_mem_access(const uint32_t byte_addr, uint32_t& data, const int type, con
210218
else if ((type & MEM_NOT_DBG_MASK) == MEM_WR_ACCESS_WORD && byte_addr == INT_ADDR)
211219
{
212220
irq = data & 0x1;
213-
processed = 1;
221+
processed = 0;
214222
}
215223

216224
return processed;

iss/src/rv32csr_cpu.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ void rv32csr_cpu::process_trap(int trap_type)
122122
}
123123

124124
state.hart[curr_hart].pc = (state.hart[curr_hart].csr[RV32CSR_ADDR_MTVEC] & ~RV32CSR_MTVEC_MODE_MASK) + offset;
125+
cycle_count += RV32I_TRAP_EXTRA_CYCLES;
125126
}
126127

127128
int rv32csr_cpu::process_interrupts()
@@ -231,9 +232,11 @@ uint32_t rv32csr_cpu::access_csr(const unsigned funct3, const uint32_t addr, con
231232
{
232233
prev_rd_value = (uint32_t)state.hart[curr_hart].x[rd];
233234

234-
// Take this opportunity to update the cycle count registers
235-
state.hart[curr_hart].csr[RV32CSR_ADDR_MCYCLE] = clk_cycles() & 0xffffffff;
236-
state.hart[curr_hart].csr[RV32CSR_ADDR_MCYCLEH] = (clk_cycles() >> 32) & 0xffffffff;
235+
// Take this opportunity to update the cycle count and instructions retired registers
236+
state.hart[curr_hart].csr[RV32CSR_ADDR_MCYCLE] = clk_cycles() & 0xffffffff;
237+
state.hart[curr_hart].csr[RV32CSR_ADDR_MCYCLEH] = (clk_cycles() >> 32) & 0xffffffff;
238+
state.hart[curr_hart].csr[RV32CSR_ADDR_MINSTRET] = inst_retired() & 0xffffffff;
239+
state.hart[curr_hart].csr[RV32CSR_ADDR_MINSTRETH] = (inst_retired() >> 32) & 0xffffffff;
237240

238241
state.hart[curr_hart].x[rd] = state.hart[curr_hart].csr[addr & 0xfff];
239242
}

iss/src/rv32i_cpu.cpp

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ rv32i_cpu::rv32i_cpu(FILE* dbg_fp) : dasm_fp(dbg_fp)
4747
// Cycle count set to 0
4848
cycle_count = 0;
4949

50+
// Instructions retired count set to 0
51+
instret_count = 0;
52+
5053
// Default the current instruction to an unimplemented instruction
5154
curr_instr = 0x00000000;
5255

@@ -327,7 +330,12 @@ int rv32i_cpu::execute(rv32i_decode_t& decode, rv32i_decode_table_t* p_entry)
327330

328331
(this->*p_entry->p)(&decode);
329332

330-
cycle_count += 1;
333+
// Update cycle count and instructions retired count. By default, the timing model
334+
// assumes 1 cycle for each instruction. For jumps and branches, additional cycles
335+
// are added in the instruction methods. For memory accesses, the external callbacks
336+
// return wait state couts, which are added.
337+
cycle_count += RV32I_DEFAULT_INSTR_CYCLE_COUNT;
338+
instret_count += 1;
331339

332340
// If an illegal/unimplemented instruction, or halt on a system instruction, flag to calling function
333341
if ((halt_rsvd_instr && trap) || (halt_ecall && (trap == SIGTERM || trap == SIGTRAP)))
@@ -1110,6 +1118,7 @@ void rv32i_cpu::beq(const p_rv32i_decode_t d)
11101118
else
11111119
{
11121120
state.hart[curr_hart].pc = access_addr;
1121+
cycle_count += RV32I_BRANCH_TAKEN_EXTRA_CYCLES;
11131122
RV32I_DISASSEM_PC_JUMP;
11141123
}
11151124
}
@@ -1135,6 +1144,7 @@ void rv32i_cpu::bne(const p_rv32i_decode_t d)
11351144
else
11361145
{
11371146
state.hart[curr_hart].pc = access_addr;
1147+
cycle_count += RV32I_BRANCH_TAKEN_EXTRA_CYCLES;
11381148
RV32I_DISASSEM_PC_JUMP;
11391149
}
11401150
}
@@ -1160,6 +1170,7 @@ void rv32i_cpu::blt(const p_rv32i_decode_t d)
11601170
else
11611171
{
11621172
state.hart[curr_hart].pc = access_addr;
1173+
cycle_count += RV32I_BRANCH_TAKEN_EXTRA_CYCLES;
11631174
RV32I_DISASSEM_PC_JUMP;
11641175
}
11651176
}
@@ -1185,6 +1196,7 @@ void rv32i_cpu::bge(const p_rv32i_decode_t d)
11851196
else
11861197
{
11871198
state.hart[curr_hart].pc = access_addr;
1199+
cycle_count += RV32I_BRANCH_TAKEN_EXTRA_CYCLES;
11881200
RV32I_DISASSEM_PC_JUMP;
11891201
}
11901202
}
@@ -1210,6 +1222,7 @@ void rv32i_cpu::bltu(const p_rv32i_decode_t d)
12101222
else
12111223
{
12121224
state.hart[curr_hart].pc = access_addr;
1225+
cycle_count += RV32I_BRANCH_TAKEN_EXTRA_CYCLES;
12131226
RV32I_DISASSEM_PC_JUMP;
12141227
}
12151228
}
@@ -1235,6 +1248,7 @@ void rv32i_cpu::bgeu(const p_rv32i_decode_t d)
12351248
else
12361249
{
12371250
state.hart[curr_hart].pc = access_addr;
1251+
cycle_count += RV32I_BRANCH_TAKEN_EXTRA_CYCLES;
12381252
RV32I_DISASSEM_PC_JUMP;
12391253
}
12401254
}
@@ -1270,6 +1284,7 @@ void rv32i_cpu::jal(const p_rv32i_decode_t d)
12701284
}
12711285

12721286
state.hart[curr_hart].pc = access_addr;
1287+
cycle_count += RV32I_JUMP_INSTR_EXTRA_CYCLES;
12731288
}
12741289
}
12751290
else
@@ -1297,6 +1312,7 @@ void rv32i_cpu::jalr(const p_rv32i_decode_t d)
12971312
else
12981313
{
12991314
state.hart[curr_hart].pc = access_addr;
1315+
cycle_count += RV32I_JUMP_INSTR_EXTRA_CYCLES;
13001316

13011317
if (d->rd)
13021318
{

iss/src/rv32i_cpu.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,9 @@ class rv32i_cpu
147147
// Protected member variables
148148
// ------------------------------------------------
149149
protected:
150+
// Clock cycle count. Protected status so that rvcsr_cpu overriding of process_trap()
151+
// method can update it on exceptions.
152+
rv32i_time_t cycle_count;
150153

151154
// ------------------------------------------------
152155
// Internal constant definitions
@@ -272,8 +275,10 @@ class rv32i_cpu
272275
// Internal memory
273276
uint8_t internal_mem [4*RV32I_INT_MEM_WORDS+4];
274277

275-
rv32i_time_t cycle_count;
278+
// Instructions retired count
279+
rv32i_time_t instret_count;
276280

281+
// Real time counter comparator value
277282
rv32i_time_t mtimecmp;
278283

279284
// String forming scratch space
@@ -329,6 +334,7 @@ class rv32i_cpu
329334
virtual void process_trap(int trap_type = 0)
330335
{
331336
state.hart[curr_hart].pc = RV32I_FIXED_MTVEC_ADDR;
337+
cycle_count += RV32I_TRAP_EXTRA_CYCLES;
332338
}
333339

334340
// Virtual place holder for adding interrupt features
@@ -396,6 +402,10 @@ class rv32i_cpu
396402
return cycle_count;
397403
}
398404

405+
inline uint64_t inst_retired() {
406+
return instret_count;
407+
}
408+
399409
inline uint32_t get_curr_instruction()
400410
{
401411
return curr_instr;

iss/src/rv32i_cpu_hdr.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,12 @@
263263
#define RV32I_QNAND 0x7ff8000000000000UL
264264
#define RV32I_SNAND 0x7ff0000000000001UL
265265

266+
// Timing model definitions
267+
#define RV32I_DEFAULT_INSTR_CYCLE_COUNT 1
268+
#define RV32I_JUMP_INSTR_EXTRA_CYCLES 3
269+
#define RV32I_BRANCH_TAKEN_EXTRA_CYCLES 3
270+
#define RV32I_TRAP_EXTRA_CYCLES 3
271+
266272
// -------------------------------------------------------------------------
267273
// MACROS
268274
// -------------------------------------------------------------------------

0 commit comments

Comments
 (0)