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
Ejemplo n.º 2
0
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
Ejemplo n.º 3
0
    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