def _process_core_sim_log_fd(log_fd, csv_fd, full_trace=True): """Process core simulation log. Reads from log_fd, which should be a file object containing a trace from an core simulation. Writes in a standard CSV format to csv_fd, which should be a file object opened for writing. If full_trace is true, this dumps information about operands for, replacing absolute branch destinations with offsets relative to the current pc. """ instr_cnt = 0 trace_csv = RiscvInstructionTraceCsv(csv_fd) trace_csv.start_new_trace() trace_entry = None for line in log_fd: if re.search("ecall", line): break # Extract instruction information m = INSTR_RE.search(line) if m: instr_cnt += 1 # Write the extracted instruction to a csvcol buffer file trace_entry = RiscvInstructionTraceEntry() trace_entry.instr_str = m.group("instr") trace_entry.instr = m.group("instr").split()[0] trace_entry.pc = m.group("pc") trace_entry.binary = m.group("bin") if full_trace: # Convert the operands into ABI format for # the functional coverage flow operands = m.group("instr").split()[1] trace_entry.operand = convert_operands_to_abi(operands) process_trace(trace_entry) c = RD_RE.search(line) if c: trace_entry.gpr.append('{}:{}'.format( gpr_to_abi("x%0s" % c.group("rd")), c.group("rd_val"))) trace_csv.write_trace_entry(trace_entry) return instr_cnt
def _process_ibex_sim_log_fd(log_fd, csv_fd, full_trace=True): """Process ibex simulation log. Reads from log_fd, which should be a file object containing a trace from an Ibex simulation. Writes in a standard CSV format to csv_fd, which should be a file object opened for writing. If full_trace is true, this dumps information about operands for, replacing absolute branch destinations with offsets relative to the current pc. """ instr_cnt = 0 trace_csv = RiscvInstructionTraceCsv(csv_fd) trace_csv.start_new_trace() trace_entry = None for line in log_fd: if re.search("ecall", line): break # Extract instruction information m = INSTR_RE.search(line) if m is None: continue instr_cnt += 1 # Write the extracted instruction to a csvcol buffer file trace_entry = RiscvInstructionTraceEntry() trace_entry.instr_str = m.group("instr") trace_entry.instr = m.group("instr").split()[0] trace_entry.pc = m.group("pc") trace_entry.binary = m.group("bin") if full_trace: expand_trace_entry(trace_entry, m.group("instr").split()[1]) c = RD_RE.search(line) if c: abi_name = gpr_to_abi("x{}".format(c.group("rd"))) gpr_entry = "{}:{}".format(abi_name, c.group("rd_val")) trace_entry.gpr.append(gpr_entry) trace_csv.write_trace_entry(trace_entry) return instr_cnt
def aux(): csv_output_fd = csv_output.open("w") csv_writer = RiscvInstructionTraceCsv(csv_fd=csv_output_fd) csv_writer.start_new_trace() total_num_processed = -1 prev_checkpoint = 0 do_compare = lambda : total_num_processed - prev_checkpoint >= compare_every while True: instr : int = yield cpu.instr pc : int = yield cpu.pc if (yield cpu.fetch): total_num_processed += 1 if do_compare(): csv_output_fd.flush() logging.info(f"total: {total_num_processed}, previous checkpoint: {prev_checkpoint}. calling 'compare_trace_csv'...") prev_checkpoint = total_num_processed # order of passing mtkcpu and spike matters - we allow only first passed log to be shorter compare_trace_csv(csv_output.absolute(), iss_csv.absolute(), "mtkcpu", "spike", log=0) instr_disas = disassemble(instr) logging.info(f"{hex(pc)}: {hex(instr)} : {instr_disas}") instr_str = str(instr_disas) if instr_disas else "unknown" entry = RiscvInstructionTraceEntry() entry.pc = hex(pc)[2:] entry.instr_str = instr_str instr_str_splitted = " ".join(instr_str.split()).split(" ") reg_name = instr_str_splitted[1][:-1] if len(instr_str_splitted) > 1 else "NO REG NAME" entry.binary = hex(instr)[2:] entry.mode = "3" # '3' stands for machine mode # entry.gpr value is unknown, need to calculate it if instr == 0x73: # 'ecall' - Spike simulation finishes with ecall. By default we compare with Spike. logging.critical(f"found {hex(instr)} : {instr_str} intruction: finishing simulation") return timeout_cyc = 50 found = False for _ in range(timeout_cyc): if (yield cpu.writeback): if not (yield cpu.should_write_rd): logging.info(f"detected instruction that doesn't write to rd. - {instr_str}") found = True csv_output_fd.write(f"# {hex(instr)}: {instr_str}\n") break en = yield cpu.reg_write_port.en assert en rd = yield cpu.reg_write_port.addr data = yield cpu.reg_write_port.data if instr_disas and getattr(instr_disas, "rd", None): if rd != instr_disas.rd: raise ValueError(f"{hex(instr)} reg {rd} != expected {instr_disas.rd}") else: found = True entry.gpr = [ f"{reg_name}:{hex(data)[2:]}" ] # depending on '-f' param passed to 'scripts/spike_log_to_trace_csv.py' inside riscv-dv repo, # we need either to print register-state-changing instructions only (like here), # or all instructions, then we would put the line below after the loop. csv_writer.write_trace_entry(entry) break yield if not found: raise ValueError("No register write observed!") yield