OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /openrisc/trunk/orpsocv2/bench/sysc/src
    from Rev 49 to Rev 51
    Reverse comparison

Rev 49 → Rev 51

/Or1200MonitorSC.cpp
46,10 → 46,12
 
Or1200MonitorSC::Or1200MonitorSC (sc_core::sc_module_name name,
OrpsocAccess *_accessor,
MemoryLoad *_memoryload,
int argc,
char *argv[]) :
sc_module (name),
accessor (_accessor)
accessor (_accessor),
memoryload(_memoryload)
{
 
// If not -log option, then don't log
56,6 → 58,10
string logfileDefault("vlt-executed.log");
string logfileNameString;
int profiling_enabled = 0;
string profileFileName(DEFAULT_PROF_FILE);
insn_count=0;
cycle_count=0;
 
exit_perf_summary_enabled = 1; // Simulation exit performance summary is
// on by default. Turn off with "-q" on the cmd line
72,23 → 78,44
{
logfileNameString = (argv[i+1]);
cmdline_name_found=1;
break;
}
}
// Search through the command line parameters for the "-q","--no-perf-summary" option
for(int i=1; i < argc; i++)
{
if ((strcmp(argv[i], "-q")==0) ||
(strcmp(argv[i], "--quiet")==0))
else if ((strcmp(argv[i], "-q")==0) ||
(strcmp(argv[i], "--quiet")==0))
{
exit_perf_summary_enabled = 0;
break;
}
else if ((strcmp(argv[i], "-p")==0) ||
(strcmp(argv[i], "--profile")==0))
{
profiling_enabled = 1;
// Check for !end of command line and it's not a command
if ((i+1 < argc)){
if(argv[i+1][0] != '-')
profileFileName = (argv[i+1]);
}
}
}
}
if (profiling_enabled)
{
profileFile.open(profileFileName.c_str(), ios::out); // Open profiling log file
if(profileFile.is_open())
{
// If the file was opened OK, then enabled logging and print a message.
profiling_enabled = 1;
cout << "* Execution profiling enabled. Logging to " << profileFileName << endl;
}
// Setup profiling function
SC_METHOD (callLog);
sensitive << clk.pos();
dont_initialize();
start = clock();
}
 
if(cmdline_name_found==1) // No -log option specified so don't turn on logging
{
 
103,13 → 130,15
}
}
if (logging_enabled)
{
SC_METHOD (displayState);
sensitive << clk.pos();
dont_initialize();
start = clock();
}
 
SC_METHOD (displayState);
sensitive << clk.pos();
dont_initialize();
start = clock();
 
// checkInstruction monitors the bus for special NOP instructionsl
SC_METHOD (checkInstruction);
124,7 → 153,7
void
Or1200MonitorSC::printSwitches()
{
printf(" [-l <file>] [-q]");
printf(" [-l <file>] [-q] [-p [<file>]]");
}
 
//! Print usage for the options of this module
131,6 → 160,7
void
Or1200MonitorSC::printUsage()
{
printf(" -p, --profile\t\tEnable execution profiling output to file (default "DEFAULT_PROF_FILE")\n");
printf(" -l, --log\t\tLog processor execution to file\n");
printf(" -q, --quiet\t\tDisable the performance summary at end of simulation\n");
}
150,7 → 180,7
{
uint32_t r3;
double ts;
 
// Check the instruction when the freeze signal is low.
if (!accessor->getWbFreeze())
{
194,11 → 224,79
} // checkInstruction()
 
 
//! Method to log execution in terms of calls and returns
 
void
Or1200MonitorSC::callLog()
{
uint32_t exinsn, delaypc;
uint32_t o_a; // operand a
uint32_t o_b; // operand b
struct label_entry *tmp;
cycle_count++;
// Instructions should be valid when freeze is low and there are no exceptions
//if (!accessor->getExFreeze())
if ((!accessor->getWbFreeze()) && (accessor->getExceptType() == 0))
{
// Increment instruction counter
insn_count++;
 
//exinsn = accessor->getExInsn();// & 0x3ffffff;
exinsn = accessor->getWbInsn();
// Check the instruction
switch((exinsn >> 26) & 0x3f) { // Check Opcode - top 6 bits
case 0x1:
/* Instruction: l.jal */
o_a = (exinsn >> 0) & 0x3ffffff;
if(o_a & 0x02000000) o_a |= 0xfe000000;
//delaypc = accessor->getExPC() + (o_a * 4); // PC we're jumping to
delaypc = accessor->getWbPC() + (o_a * 4); // PC we're jumping to
// Now we have info about where we're jumping to. Output the info, with label if possible
// We print the PC we're jumping from + 8 which is the return address
if ( tmp = memoryload->get_label (delaypc) )
profileFile << "+" << std::setfill('0') << hex << std::setw(8) << cycle_count << " " << hex << std::setw(8) << accessor->getWbPC() + 8 << " " << hex << std::setw(8) << delaypc << " " << tmp->name << endl;
else
profileFile << "+" << std::setfill('0') << hex << std::setw(8) << cycle_count << " " << hex << std::setw(8) << accessor->getWbPC() + 8 << " " << hex << std::setw(8) << delaypc << " @" << hex << std::setw(8) << delaypc << endl;
break;
case 0x11:
/* Instruction: l.jr */
// Bits 15-11 contain register number
o_b = (exinsn >> 11) & 0x1f;
if (o_b == 9) // l.jr r9 is typical return
{
// Now get the value in this register
delaypc = accessor->getGpr(o_b);
// Output this jump
profileFile << "-" << std::setfill('0') << hex << std::setw(8) << cycle_count << " " << hex << std::setw(8) << delaypc << endl;
}
break;
case 0x12:
/* Instruction: l.jalr */
o_b = (exinsn >> 11) & 0x1f;
// Now get the value in this register
delaypc = accessor->getGpr(o_b);
// Now we have info about where we're jumping to. Output the info, with label if possible
// We print the PC we're jumping from + 8 which is the return address
if ( tmp = memoryload->get_label (delaypc) )
profileFile << "+" << std::setfill('0') << hex << std::setw(8) << cycle_count << " " << hex << std::setw(8) << accessor->getWbPC() + 8 << " " << hex << std::setw(8) << delaypc << " " << tmp->name << endl;
else
profileFile << "+" << std::setfill('0') << hex << std::setw(8) << cycle_count << " " << hex << std::setw(8) << accessor->getWbPC() + 8 << " " << hex << std::setw(8) << delaypc << " @" << hex << std::setw(8) << delaypc << endl;
break;
 
}
}
} // checkInstruction()
 
 
//! Method to output the state of the processor
 
//! This function will output to a file, if enabled, the status of the processor
//! For now, it's just the PPC and instruction.
#define PRINT_REGS 0
#define PRINT_REGS 1
void
Or1200MonitorSC::displayState()
{
206,8 → 304,6
// Calculate how many instructions we've actually calculated by ignoring cycles where we're frozen, delay slots and flushpipe cycles
if ((!accessor->getWbFreeze()) && !(accessor->getExceptFlushpipe() && accessor->getExDslot()))
// Increment instruction counter
insn_count++;
 
if (logging_enabled == 0)
return; // If we didn't inialise a file, then just return.
215,8 → 311,8
// Output the state if we're not frozen and not flushing during a delay slot
if ((!accessor->getWbFreeze()) && !(accessor->getExceptFlushpipe() && accessor->getExDslot()))
{
// Print PC, instruction
statusFile << "\nEXECUTED("<< std::setfill(' ') << std::setw(11) << dec << insn_count << "): " << std::setfill('0') << hex << std::setw(8) << accessor->getWbPC() << ": " << hex << accessor->getWbInsn() << endl;
// Print PC, instruction
statusFile << "\nEXECUTED("<< std::setfill(' ') << std::setw(11) << dec << insn_count << "): " << std::setfill('0') << hex << std::setw(8) << accessor->getWbPC() << ": " << hex << accessor->getWbInsn() << endl;
#if PRINT_REGS
// Print general purpose register contents
for (int i=0; i<32; i++)
/OrpsocAccess.cpp
39,6 → 39,10
#include "Vorpsoc_top_or1200_sprs.h"
#include "Vorpsoc_top_or1200_rf.h"
#include "Vorpsoc_top_or1200_dpram.h"
//#include "Vorpsoc_top_ram_wb.h"
//#include "Vorpsoc_top_ram_wb_sc_sw.h"
#include "Vorpsoc_top_ram_wb__D20_A18_M800000.h"
#include "Vorpsoc_top_ram_wb_sc_sw__D20_A18_M800000.h"
 
//! Constructor for the ORPSoC access class
 
53,10 → 57,21
or1200_except = orpsoc_top->v->i_or1k->i_or1200_top->or1200_cpu->or1200_except;
or1200_sprs = orpsoc_top->v->i_or1k->i_or1200_top->or1200_cpu->or1200_sprs;
rf_a = orpsoc_top->v->i_or1k->i_or1200_top->or1200_cpu->or1200_rf->rf_a;
ram_wb_sc_sw = orpsoc_top->v->ram_wb0->ram0;
 
} // OrpsocAccess ()
 
//! Access for the ex_freeze signal
 
//! @return The value of the or1200_ctrl.ex_freeze signal
 
bool
OrpsocAccess::getExFreeze ()
{
return or1200_ctrl->ex_freeze;
 
} // getExFreeze ()
 
//! Access for the wb_freeze signal
 
//! @return The value of the or1200_ctrl.wb_freeze signal
90,6 → 105,18
 
} // getExDslot ()
 
//! Access for the except_type value
 
//! @return The value of the or1200_except.except_type register
 
uint32_t
OrpsocAccess::getExceptType ()
{
return (or1200_except->get_except_type) ();
 
} // getExceptType ()
 
 
//! Access for the id_pc register
 
//! @return The value of the or1200_except.id_pc register
101,6 → 128,17
 
} // getIdPC ()
 
//! Access for the ex_pc register
 
//! @return The value of the or1200_except.id_ex register
 
uint32_t
OrpsocAccess::getExPC ()
{
return (or1200_except->get_ex_pc) ();
 
} // getExPC ()
 
//! Access for the wb_pc register
 
//! @return The value of the or1200_except.wb_pc register
112,6 → 150,29
 
} // getWbPC ()
 
//! Access for the id_insn register
 
//! @return The value of the or1200_ctrl.wb_insn register
 
uint32_t
OrpsocAccess::getIdInsn ()
{
return (or1200_ctrl->get_id_insn) ();
 
} // getIdInsn ()
 
//! Access for the ex_insn register
 
//! @return The value of the or1200_ctrl.ex_insn register
 
uint32_t
OrpsocAccess::getExInsn ()
{
return (or1200_ctrl->get_ex_insn) ();
 
} // getExInsn ()
 
 
//! Access for the wb_insn register
 
//! @return The value of the or1200_ctrl.wb_insn register
123,17 → 184,35
 
} // getWbInsn ()
 
//! Access for the id_insn register
//! Access the Wishbone SRAM memory
 
//! @return The value of the or1200_ctrl.wb_insn register
//! @return The value of the memory word at addr
 
uint32_t
OrpsocAccess::getIdInsn ()
OrpsocAccess::get_mem (uint32_t addr)
{
return (or1200_ctrl->get_id_insn) ();
return (ram_wb_sc_sw->get_mem) (addr);
 
} // getIdInsn ()
} // get_mem ()
 
//! Write value to the Wishbone SRAM memory
 
void
OrpsocAccess::set_mem (uint32_t addr, uint32_t data)
{
(ram_wb_sc_sw->set_mem) (addr, data);
 
} // set_mem ()
 
//! Trigger the $readmemh() system call
 
void
OrpsocAccess::do_ram_readmemh (void)
{
(ram_wb_sc_sw->do_readmemh) ();
 
} // do_ram_readmemh ()
 
//! Access for the OR1200 GPRs
 
//! These are extracted from memory using the Verilog function
/MemoryLoad.cpp
0,0 → 1,979
/* MemoryLoad.cpp -- Program load functions
 
Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
Copyright (C) 2008 Embecosm Limited
Copyright (C) 2009 Julius Baxter, julius@orsoc.se
 
Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
 
This file is part of Or1ksim, the OpenRISC 1000 Architectural Simulator.
 
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your option)
any later version.
 
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
 
You should have received a copy of the GNU General Public License along
with this program. If not, see <http://www.gnu.org/licenses/>. */
 
/* This program is commented throughout in a fashion suitable for processing
with Doxygen. */
 
/* System includes */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
#include "MemoryLoad.h"
#include "OrpsocMain.h"
 
 
//! Constructor for the ORPSoC memory loader class
 
//! Initializes various values
 
//! @param[in] orpsoc The SystemC Verilated ORPSoC instance
//! @param[in] accessor Accessor class for this Verilated ORPSoC model
 
MemoryLoad::MemoryLoad
(
OrpsocAccess *_accessor
)
{
accessor = _accessor;
} // MemoryAccess ()
 
 
/*---------------------------------------------------------------------------*/
/*!Copy a string with null termination
 
This function is very similar to strncpy, except it null terminates the
string. A global function also used by the CUC.
 
@param[in] dst The destination string
@param[in] src The source string
@param[in] n Number of chars to copy EXCLUDING the null terminator
(i.e. dst had better have room for n+1 chars)
 
@return A pointer to dst */
/*---------------------------------------------------------------------------*/
char *
MemoryLoad::strstrip (char *dst,
const char *src,
int n)
{
strncpy (dst, src, n);
*(dst + n) = '\0';
 
return dst;
 
} /* strstrip () */
 
/*---------------------------------------------------------------------------*/
/*!Translate logical to physical addresses for the loader
 
Used only by the simulator loader to translate logical addresses into
physical. If loadcode() is called with valid @c virtphy_transl pointer to
a table of translations then translate() performs translation otherwise
physical address is equal to logical.
Currently NOT used
 
@param[in] laddr Logical address
@param[in] breakpoint Unused
 
@return The physical address */
/*---------------------------------------------------------------------------*/
oraddr_t
MemoryLoad::translate (oraddr_t laddr,
int *breakpoint)
{
/*
int i;
// No translation (i.e. when loading kernel into simulator)
if (transl_table == 0)
{
return laddr;
}
 
// Try to find our translation in the table.
for (i = 0; i < (MEMORY_LEN / PAGE_SIZE) * 16; i += 16)
{
if ((laddr & ~(PAGE_SIZE - 1)) == eval_direct32 (transl_table + i, 0, 0))
{
// Page modified
set_direct32 (transl_table + i + 8, -2, 0, 0);
PRINTF ("found paddr=%" PRIx32 "\n",
eval_direct32 (transl_table + i + 4, 0, 0) |
(laddr & (PAGE_SIZE - 1)));
return (oraddr_t) eval_direct32 (transl_table + i + 4, 0, 0) |
(laddr & (oraddr_t) (PAGE_SIZE - 1));
}
}
 
// Allocate new phy page for us.
for (i = 0; i < (MEMORY_LEN / PAGE_SIZE) * 16; i += 16)
{
if (eval_direct32 (transl_table + i + 8, 0, 0) == 0)
{
// VPN
set_direct32 (transl_table + i, laddr & ~(PAGE_SIZE - 1), 0, 0);
// PPN
set_direct32 (transl_table + i + 4, (i / 16) * PAGE_SIZE, 0, 0);
// Page modified
//set_direct32 (transl_table + i + 8, -2, 0, 0);
PRINTF ("newly allocated ppn=%" PRIx32 "\n",
eval_direct32 (transl_table + i + 4, 0, 0));
PRINTF ("newly allocated .ppn=%" PRIxADDR "\n", transl_table + i + 4);
PRINTF ("newly allocated ofs=%" PRIxADDR "\n",
(laddr & (PAGE_SIZE - 1)));
PRINTF ("newly allocated paddr=%" PRIx32 "\n",
eval_direct32 (transl_table + i + 4, 0,
0) | (laddr & (PAGE_SIZE - 1)));
return (oraddr_t) eval_direct32 (transl_table + i + 4, 0, 0) |
(laddr & (oraddr_t) (PAGE_SIZE - 1));
}
}
 
// If we come this far then all phy memory is used and we can't find our
page nor allocate new page.
transl_error = 1;
PRINTF ("can't translate %" PRIxADDR "\n", laddr);
exit (1);
 
return -1;
*/
return 0;
 
} /* translate() */
 
#if IMM_STATS
int
MemoryLoad::bits (uint32_t val)
{
int i = 1;
if (!val)
return 0;
while (val != 0 && (int32_t) val != -1)
{
i++;
val = (int32_t) val >> 1;
}
return i;
}
 
void
MemoryLoad::check_insn (uint32_t insn)
{
int insn_index = insn_decode (insn);
struct insn_op_struct *opd = op_start[insn_index];
uint32_t data = 0;
int dis = 0;
const char *name;
if (!insn || insn_index < 0)
return;
name = insn_name (insn_index);
if (strcmp (name, "l.nop") == 0 || strcmp (name, "l.sys") == 0)
return;
 
while (1)
{
uint32_t tmp = 0 unsigned int nbits = 0;
while (1)
{
tmp |=
((insn >> (opd->type & OPTYPE_SHR)) & ((1 << opd->data) - 1)) <<
nbits;
nbits += opd->data;
if (opd->type & OPTYPE_OP)
break;
opd++;
}
 
/* Do we have to sign extend? */
if (opd->type & OPTYPE_SIG)
{
int sbit = (opd->type & OPTYPE_SBIT) >> OPTYPE_SBIT_SHR;
if (tmp & (1 << sbit))
tmp |= 0xFFFFFFFF << sbit;
}
if (opd->type & OPTYPE_DIS)
{
/* We have to read register later. */
data += tmp;
dis = 1;
}
else
{
if (!(opd->type & OPTYPE_REG) || dis)
{
if (!dis)
data = tmp;
if (strcmp (name, "l.movhi") == 0)
{
movhi = data << 16;
}
else
{
data |= movhi;
//PRINTF ("%08x %s\n", data, name);
if (!(or32_opcodes[insn_index].flags & OR32_IF_DELAY))
{
bcnt[bits (data)][0]++;
bsum[0]++;
}
else
{
if (strcmp (name, "l.bf") == 0
|| strcmp (name, "l.bnf") == 0)
{
bcnt[bits (data)][1]++;
bsum[1]++;
}
else
{
bcnt[bits (data)][2]++;
bsum[2]++;
}
}
}
}
data = 0;
dis = 0;
}
if (opd->type & OPTYPE_LAST)
{
return;
}
opd++;
}
}
#endif
 
/*---------------------------------------------------------------------------*/
/*!Add an instruction to the program
 
@note insn must be in big endian format
 
@param[in] address The address to use
@param[in] insn The instruction to add
@param[in] breakpoint Not used (it is passed to the translate() function,
which also does not use it. */
/*---------------------------------------------------------------------------*/
void
MemoryLoad::addprogram (oraddr_t address,
uint32_t insn,
int *breakpoint)
{
// Memory is word addressed, not byte, so /4 the address we get
int vaddr = (int) address/4; /*(!runtime.sim.filename) ? translate (address, breakpoint) :
translate (freemem, breakpoint);
-- jb
*/
/* We can't have set_program32 functions since it is not gauranteed that the
section we're loading is aligned on a 4-byte boundry */
/*
set_program8 (vaddr, (insn >> 24) & 0xff);
set_program8 (vaddr + 1, (insn >> 16) & 0xff);
set_program8 (vaddr + 2, (insn >> 8) & 0xff);
set_program8 (vaddr + 3, insn & 0xff);
*/
/* Use the whole-word write */
accessor->set_mem(vaddr, insn);
PRINTF("* addprogram: addr 0x%.8x insn: 0x%.8x (conf: 0x%.8x)\n", vaddr, insn, accessor->get_mem(vaddr));
 
#if IMM_STATS
check_insn (insn);
#endif
//if (runtime.sim.filename)
//{
//freemem += insn_len (insn_decode (insn));
//}
freemem += 4;
} /* addprogram () */
 
 
/*---------------------------------------------------------------------------*/
/*!Load big-endian COFF file
 
@param[in] filename File to load
@param[in] sections Number of sections in file */
/*---------------------------------------------------------------------------*/
void
MemoryLoad::readfile_coff (char *filename,
short sections)
{
FILE *inputfs;
char inputbuf[4];
uint32_t insn;
int32_t sectsize;
COFF_AOUTHDR coffaouthdr;
struct COFF_scnhdr coffscnhdr;
int len;
int firstthree = 0;
int breakpoint = 0;
 
if (!(inputfs = fopen (filename, "r")))
{
perror ("readfile_coff");
exit (1);
}
 
if (fseek (inputfs, sizeof (COFF_FILHDR), SEEK_SET) == -1)
{
fclose (inputfs);
perror ("readfile_coff");
exit (1);
}
 
if (fread (&coffaouthdr, sizeof (coffaouthdr), 1, inputfs) != 1)
{
fclose (inputfs);
perror ("readfile_coff");
exit (1);
}
 
while (sections--)
{
uint32_t scnhdr_pos =
sizeof (COFF_FILHDR) + sizeof (coffaouthdr) +
sizeof (struct COFF_scnhdr) * firstthree;
if (fseek (inputfs, scnhdr_pos, SEEK_SET) == -1)
{
fclose (inputfs);
perror ("readfile_coff");
exit (1);
}
if (fread (&coffscnhdr, sizeof (struct COFF_scnhdr), 1, inputfs) != 1)
{
fclose (inputfs);
perror ("readfile_coff");
exit (1);
}
PRINTF ("Section: %s,", coffscnhdr.s_name);
PRINTF (" paddr: 0x%.8lx,", COFF_LONG_H (coffscnhdr.s_paddr));
PRINTF (" vaddr: 0x%.8lx,", COFF_LONG_H (coffscnhdr.s_vaddr));
PRINTF (" size: 0x%.8lx,", COFF_LONG_H (coffscnhdr.s_size));
PRINTF (" scnptr: 0x%.8lx\n", COFF_LONG_H (coffscnhdr.s_scnptr));
 
sectsize = COFF_LONG_H (coffscnhdr.s_size);
++firstthree;
 
/* loading section */
freemem = COFF_LONG_H (coffscnhdr.s_paddr);
if (fseek (inputfs, COFF_LONG_H (coffscnhdr.s_scnptr), SEEK_SET) == -1)
{
fclose (inputfs);
perror ("readfile_coff");
exit (1);
}
while (sectsize > 0
&& (len = fread (&inputbuf, sizeof (inputbuf), 1, inputfs)))
{
insn = COFF_LONG_H (inputbuf);
//len = insn_len (insn_decode (insn));
len = 4;
if (len == 2)
{
fseek (inputfs, -2, SEEK_CUR);
}
 
addprogram (freemem, insn, &breakpoint);
sectsize -= len;
}
}
if (firstthree < 3)
{
PRINTF ("One or more missing sections. At least");
PRINTF (" three sections expected (.text, .data, .bss).\n");
exit (1);
}
if (firstthree > 3)
{
PRINTF ("Warning: one or more extra sections. These");
PRINTF (" sections were handled as .data sections.\n");
}
 
fclose (inputfs);
PRINTF ("Finished loading COFF.\n");
return;
 
} /* readfile_coff () */
 
 
/*---------------------------------------------------------------------------*/
/*!Load symbols from big-endian COFF file
 
@param[in] filename File to load
@param[in] symptr Symbol pointer value
@param[in] syms Symbols value */
/*---------------------------------------------------------------------------*/
 
void
MemoryLoad::readsyms_coff (char *filename, uint32_t symptr, uint32_t syms)
{
FILE *inputfs;
struct COFF_syment coffsymhdr;
int count = 0;
uint32_t nsyms = syms;
if (!(inputfs = fopen (filename, "r")))
{
perror ("readsyms_coff");
exit (1);
}
 
if (fseek (inputfs, symptr, SEEK_SET) == -1)
{
fclose (inputfs);
perror ("readsyms_coff");
exit (1);
}
 
while (syms--)
{
int i, n;
if (fread (&coffsymhdr, COFF_SYMESZ, 1, inputfs) != 1)
{
fclose (inputfs);
perror ("readsyms_coff");
exit (1);
}
 
n = (unsigned char) coffsymhdr.e_numaux[0];
 
/* check whether this symbol belongs to a section and is external
symbol; ignore all others */
if (COFF_SHORT_H (coffsymhdr.e_scnum) >= 0
&& coffsymhdr.e_sclass[0] == C_EXT)
{
if (*((uint32_t *) coffsymhdr.e.e.e_zeroes))
{
if (strlen (coffsymhdr.e.e_name)
&& strlen (coffsymhdr.e.e_name) < 9)
add_label (COFF_LONG_H (coffsymhdr.e_value),
coffsymhdr.e.e_name);
}
else
{
uint32_t fpos = ftell (inputfs);
 
if (fseek
(inputfs,
symptr + nsyms * COFF_SYMESZ +
COFF_LONG_H (coffsymhdr.e.e.e_offset), SEEK_SET) == 0)
{
char tmp[33], *s = &tmp[0];
while (s != &tmp[32])
if ((*(s++) = fgetc (inputfs)) == 0)
break;
tmp[32] = 0;
add_label (COFF_LONG_H (coffsymhdr.e_value), &tmp[0]);
}
fseek (inputfs, fpos, SEEK_SET);
}
}
 
for (i = 0; i < n; i++)
if (fread (&coffsymhdr, COFF_SYMESZ, 1, inputfs) != 1)
{
fclose (inputfs);
perror ("readsyms_coff3");
exit (1);
}
syms -= n;
count += n;
}
 
fclose (inputfs);
PRINTF ("Finished loading symbols.\n");
return;
}
 
/*---------------------------------------------------------------------------*/
/*!Read an ELF file
 
@param[in] filename File to load */
/*---------------------------------------------------------------------------*/
void
MemoryLoad::readfile_elf (char *filename)
{
 
FILE *inputfs;
struct elf32_hdr elfhdr;
struct elf32_phdr *elf_phdata = NULL;
struct elf32_shdr *elf_spnt, *elf_shdata;
struct elf32_sym *sym_tbl = (struct elf32_sym *) 0;
uint32_t syms = 0;
char *str_tbl = (char *) 0;
char *s_str = (char *) 0;
int breakpoint = 0;
uint32_t inputbuf;
uint32_t padd;
uint32_t insn;
int i, j, sectsize, len;
 
if (!(inputfs = fopen (filename, "r")))
{
perror ("readfile_elf");
exit (1);
}
 
if (fread (&elfhdr, sizeof (elfhdr), 1, inputfs) != 1)
{
perror ("readfile_elf");
exit (1);
}
 
if ((elf_shdata =
(struct elf32_shdr *) malloc (ELF_SHORT_H (elfhdr.e_shentsize) *
ELF_SHORT_H (elfhdr.e_shnum))) == NULL)
{
perror ("readfile_elf");
exit (1);
}
 
if (fseek (inputfs, ELF_LONG_H (elfhdr.e_shoff), SEEK_SET) != 0)
{
perror ("readfile_elf");
exit (1);
}
 
if (fread
(elf_shdata,
ELF_SHORT_H (elfhdr.e_shentsize) * ELF_SHORT_H (elfhdr.e_shnum), 1,
inputfs) != 1)
{
perror ("readfile_elf");
exit (1);
}
 
if (ELF_LONG_H (elfhdr.e_phoff))
{
if ((elf_phdata =
(struct elf32_phdr *) malloc (ELF_SHORT_H (elfhdr.e_phnum) *
ELF_SHORT_H (elfhdr.e_phentsize))) ==
NULL)
{
perror ("readfile_elf");
exit (1);
}
 
if (fseek (inputfs, ELF_LONG_H (elfhdr.e_phoff), SEEK_SET) != 0)
{
perror ("readfile_elf");
exit (1);
}
 
if (fread
(elf_phdata,
ELF_SHORT_H (elfhdr.e_phnum) * ELF_SHORT_H (elfhdr.e_phentsize),
1, inputfs) != 1)
{
perror ("readfile_elf");
exit (1);
}
}
 
for (i = 0, elf_spnt = elf_shdata; i < ELF_SHORT_H (elfhdr.e_shnum);
i++, elf_spnt++)
{
 
if (ELF_LONG_H (elf_spnt->sh_type) == SHT_STRTAB)
{
if (NULL != str_tbl)
{
free (str_tbl);
}
 
if ((str_tbl =
(char *) malloc (ELF_LONG_H (elf_spnt->sh_size))) == NULL)
{
perror ("readfile_elf");
exit (1);
}
 
if (fseek (inputfs, ELF_LONG_H (elf_spnt->sh_offset), SEEK_SET) !=
0)
{
perror ("readfile_elf");
exit (1);
}
 
if (fread (str_tbl, ELF_LONG_H (elf_spnt->sh_size), 1, inputfs) !=
1)
{
perror ("readfile_elf");
exit (1);
}
}
else if (ELF_LONG_H (elf_spnt->sh_type) == SHT_SYMTAB)
{
 
if (NULL != sym_tbl)
{
free (sym_tbl);
}
 
if ((sym_tbl =
(struct elf32_sym *) malloc (ELF_LONG_H (elf_spnt->sh_size)))
== NULL)
{
perror ("readfile_elf");
exit (1);
}
 
if (fseek (inputfs, ELF_LONG_H (elf_spnt->sh_offset), SEEK_SET) !=
0)
{
perror ("readfile_elf");
exit (1);
}
 
if (fread (sym_tbl, ELF_LONG_H (elf_spnt->sh_size), 1, inputfs) !=
1)
{
perror ("readfile_elf");
exit (1);
}
 
syms =
ELF_LONG_H (elf_spnt->sh_size) /
ELF_LONG_H (elf_spnt->sh_entsize);
}
}
 
if (ELF_SHORT_H (elfhdr.e_shstrndx) != SHN_UNDEF)
{
elf_spnt = &elf_shdata[ELF_SHORT_H (elfhdr.e_shstrndx)];
 
if ((s_str = (char *) malloc (ELF_LONG_H (elf_spnt->sh_size))) == NULL)
{
perror ("readfile_elf");
exit (1);
}
 
if (fseek (inputfs, ELF_LONG_H (elf_spnt->sh_offset), SEEK_SET) != 0)
{
perror ("readfile_elf");
exit (1);
}
 
if (fread (s_str, ELF_LONG_H (elf_spnt->sh_size), 1, inputfs) != 1)
{
perror ("readfile_elf");
exit (1);
}
}
 
 
for (i = 0, elf_spnt = elf_shdata; i < ELF_SHORT_H (elfhdr.e_shnum);
i++, elf_spnt++)
{
 
if ((ELF_LONG_H (elf_spnt->sh_type) & SHT_PROGBITS)
&& (ELF_LONG_H (elf_spnt->sh_flags) & SHF_ALLOC))
{
 
padd = ELF_LONG_H (elf_spnt->sh_addr);
for (j = 0; j < ELF_SHORT_H (elfhdr.e_phnum); j++)
{
if (ELF_LONG_H (elf_phdata[j].p_offset) &&
ELF_LONG_H (elf_phdata[j].p_offset) <=
ELF_LONG_H (elf_spnt->sh_offset)
&& (ELF_LONG_H (elf_phdata[j].p_offset) +
ELF_LONG_H (elf_phdata[j].p_memsz)) >
ELF_LONG_H (elf_spnt->sh_offset))
padd =
ELF_LONG_H (elf_phdata[j].p_paddr) +
ELF_LONG_H (elf_spnt->sh_offset) -
ELF_LONG_H (elf_phdata[j].p_offset);
}
 
 
 
if (ELF_LONG_H (elf_spnt->sh_name) && s_str)
PRINTF ("Section: %s,", &s_str[ELF_LONG_H (elf_spnt->sh_name)]);
else
PRINTF ("Section: noname,");
PRINTF (" vaddr: 0x%.8lx,", ELF_LONG_H (elf_spnt->sh_addr));
PRINTF (" paddr: 0x%" PRIx32, padd);
PRINTF (" offset: 0x%.8lx,", ELF_LONG_H (elf_spnt->sh_offset));
PRINTF (" size: 0x%.8lx\n", ELF_LONG_H (elf_spnt->sh_size));
 
freemem = padd;
sectsize = ELF_LONG_H (elf_spnt->sh_size);
 
if (fseek (inputfs, ELF_LONG_H (elf_spnt->sh_offset), SEEK_SET) !=
0)
{
perror ("readfile_elf");
free (elf_phdata);
exit (1);
}
 
while (sectsize > 0
&& (len = fread (&inputbuf, sizeof (inputbuf), 1, inputfs)))
{
insn = ELF_LONG_H (inputbuf);
//PRINTF("* addprogram(%.8x, %.8x, %d)\n", freemem, insn, breakpoint);
addprogram (freemem, insn, &breakpoint);
sectsize -= 4;
}
}
}
 
if (str_tbl)
{
i = 0;
while (syms--)
{
if (sym_tbl[i].st_name && sym_tbl[i].st_info
&& ELF_SHORT_H (sym_tbl[i].st_shndx) < 0x8000)
{
add_label (ELF_LONG_H (sym_tbl[i].st_value),
&str_tbl[ELF_LONG_H (sym_tbl[i].st_name)]);
}
i++;
}
}
 
if (NULL != str_tbl)
{
free (str_tbl);
}
 
if (NULL != sym_tbl)
{
free (sym_tbl);
}
 
free (s_str);
free (elf_phdata);
free (elf_shdata);
 
}
 
/* Identify file type and call appropriate readfile_X routine. It only
handles orX-coff-big executables at the moment. */
 
void
MemoryLoad::identifyfile (char *filename)
{
FILE *inputfs;
COFF_FILHDR coffhdr;
struct elf32_hdr elfhdr;
 
if (!(inputfs = fopen (filename, "r")))
{
perror (filename);
fflush (stdout);
fflush (stderr);
exit (1);
}
if (fread (&coffhdr, sizeof (coffhdr), 1, inputfs) == 1)
{
if (COFF_SHORT_H (coffhdr.f_magic) == 0x17a)
{
uint32_t opthdr_size;
PRINTF ("COFF magic: 0x%.4x\n", COFF_SHORT_H (coffhdr.f_magic));
PRINTF ("COFF flags: 0x%.4x\n", COFF_SHORT_H (coffhdr.f_flags));
PRINTF ("COFF symptr: 0x%.8lx\n", COFF_LONG_H (coffhdr.f_symptr));
if ((COFF_SHORT_H (coffhdr.f_flags) & COFF_F_EXEC) != COFF_F_EXEC)
{
PRINTF ("This COFF is not an executable.\n");
exit (1);
}
opthdr_size = COFF_SHORT_H (coffhdr.f_opthdr);
if (opthdr_size != sizeof (COFF_AOUTHDR))
{
PRINTF ("COFF optional header is missing or not recognized.\n");
PRINTF ("COFF f_opthdr: 0x%" PRIx32 "\n", opthdr_size);
exit (1);
}
fclose (inputfs);
readfile_coff (filename, COFF_SHORT_H (coffhdr.f_nscns));
readsyms_coff (filename, COFF_LONG_H (coffhdr.f_symptr),
COFF_LONG_H (coffhdr.f_nsyms));
return;
}
else
{
PRINTF ("Not COFF file format\n");
fseek (inputfs, 0, SEEK_SET);
}
}
if (fread (&elfhdr, sizeof (elfhdr), 1, inputfs) == 1)
{
if (elfhdr.e_ident[0] == 0x7f && elfhdr.e_ident[1] == 0x45
&& elfhdr.e_ident[2] == 0x4c && elfhdr.e_ident[3] == 0x46)
{
PRINTF ("ELF type: 0x%.4x\n", ELF_SHORT_H (elfhdr.e_type));
PRINTF ("ELF machine: 0x%.4x\n", ELF_SHORT_H (elfhdr.e_machine));
PRINTF ("ELF version: 0x%.8lx\n", ELF_LONG_H (elfhdr.e_version));
PRINTF ("ELF sec = %d\n", ELF_SHORT_H (elfhdr.e_shnum));
if (ELF_SHORT_H (elfhdr.e_type) != ET_EXEC)
{
PRINTF ("This ELF is not an executable.\n");
exit (1);
}
fclose (inputfs);
readfile_elf (filename);
return;
}
else
{
PRINTF ("Not ELF file format.\n");
fseek (inputfs, 0, SEEK_SET);
}
}
 
perror ("identifyfile2");
fclose (inputfs);
 
return;
}
 
 
/*---------------------------------------------------------------------------*/
/*!Load file to memory
 
Loads file to memory starting at address startaddr and returns freemem.
 
@param[in] filename File to load
@param[in] startaddr Start address at which to load
@param[in] virtphy_transl Virtual to physical transation table if
required. Only used for microkernel simulation,
and not used in Ork1sim at present (set to NULL)
 
@return zero on success, negative on failure. */
/*---------------------------------------------------------------------------*/
uint32_t
MemoryLoad::loadcode (char *filename, oraddr_t startaddr, oraddr_t virtphy_transl)
{
//int breakpoint = 0;
init_labels (); // jb
 
transl_error = 0;
transl_table = virtphy_transl;
freemem = startaddr;
PRINTF ("* MemoryLoad::loadcode: filename %s startaddr=%" PRIxADDR " virtphy_transl=%"
PRIxADDR "\n", filename, startaddr, virtphy_transl);
identifyfile (filename);
 
#if IMM_STATS
{
int i = 0, a = 0, b = 0, c = 0;
PRINTF ("index:arith/branch/jump\n");
for (i = 0; i < 33; i++)
PRINTF ("%2i:\t%3.0f%% / %3.0f%%/ %3.0f%%\t%5i / %5i / %5i\n", i,
100. * (a += bcnt[i][0]) / bsum[0], 100. * (b +=
bcnt[i][1]) /
bsum[1], 100. * (c +=
bcnt[i][2]) / bsum[2], bcnt[i][0],
bcnt[i][1], bcnt[i][2]);
PRINTF ("\nsum %i %i %i\n", bsum[0], bsum[1], bsum[2]);
}
#endif
/*
if (transl_error)
return -1;
else
return translate (freemem, &breakpoint);
*/
return (uint32_t) freemem;
 
}
 
/* From arch sim labels.c */
void
MemoryLoad::init_labels ()
{
int i;
for (i = 0; i < LABELS_HASH_SIZE; i++)
label_hash[i] = NULL;
}
 
void
MemoryLoad::add_label (oraddr_t addr, char *name)
{
struct label_entry **tmp;
tmp = &(label_hash[addr % LABELS_HASH_SIZE]);
for (; *tmp; tmp = &((*tmp)->next));
*tmp = (label_entry *) malloc (sizeof (**tmp));
(*tmp)->name = (char *) malloc (strlen (name) + 1);
(*tmp)->addr = addr;
strcpy ((*tmp)->name, name);
(*tmp)->next = NULL;
}
 
struct label_entry *
MemoryLoad::get_label (oraddr_t addr)
{
struct label_entry *tmp = label_hash[addr % LABELS_HASH_SIZE];
while (tmp)
{
if (tmp->addr == addr)
return tmp;
tmp = tmp->next;
}
return NULL;
}
 
struct label_entry *
MemoryLoad::find_label (char *name)
{
int i;
for (i = 0; i < LABELS_HASH_SIZE; i++)
{
struct label_entry *tmp = label_hash[i % LABELS_HASH_SIZE];
while (tmp)
{
if (strcmp (tmp->name, name) == 0)
return tmp;
tmp = tmp->next;
}
}
return NULL;
}
 
/* Searches mem array for a particular label and returns label's address.
If label does not exist, returns 0. */
oraddr_t
MemoryLoad::eval_label (char *name)
{
struct label_entry *le;
char *plus;
char *minus;
int positive_offset = 0;
int negative_offset = 0;
 
if ((plus = strchr (name, '+')))
{
*plus = '\0';
positive_offset = atoi (++plus);
}
 
if ((minus = strchr (name, '-')))
{
*minus = '\0';
negative_offset = atoi (++minus);
}
le = find_label (name);
if (!le)
return 0;
 
return le->addr + positive_offset - negative_offset;
}
/OrpsocMain.cpp
45,11 → 45,9
 
#include "Vorpsoc_top.h"
#include "OrpsocAccess.h"
#include "MemoryLoad.h"
 
//#if VM_TRACE
//#include <systemc.h>
#include <SpTraceVcdC.h>
//#endif
 
//#include "TraceSC.h"
#include "ResetSC.h"
107,13 → 105,18
int time_val;
int cmdline_name_found=0;
 
// Executable app load variables
int do_program_file_load = 0; // Default: we don't require a file, we use the VMEM
char* program_file; // Old char* style for program name
 
// Verilator accessor
OrpsocAccess *accessor;
 
// Modules
Vorpsoc_top *orpsoc; // Verilated ORPSoC
//TraceSC *trace; // Drive VCD
MemoryLoad *memoryload; // Memory loader
ResetSC *reset; // Generate a RESET signal
Or1200MonitorSC *monitor; // Handle l.nop x instructions
UartSC *uart; // Handle UART signals
120,24 → 123,23
 
// Instantiate the Verilator model, VCD trace handler and accessor
orpsoc = new Vorpsoc_top ("orpsoc");
//trace = new TraceSC ("trace", orpsoc, argc, argv);
accessor = new OrpsocAccess (orpsoc);
memoryload = new MemoryLoad (accessor);
// Instantiate the SystemC modules
reset = new ResetSC ("reset", BENCH_RESET_TIME);
monitor = new Or1200MonitorSC ("monitor", accessor, argc, argv);
monitor = new Or1200MonitorSC ("monitor", accessor, memoryload, argc, argv);
uart = new UartSC("uart"); // TODO: Probalby some sort of param
 
 
// Parse command line options
// Default is for VCD generation OFF, only turned on if specified on command line
dump_start_delay = 0;
dump_stop_set = 0;
dumping_now = 0;
 
// Search through the command line parameters for options
// Search through the command line parameters for options
if (argc > 1)
{
for(int i=1; i<argc; i++)
160,10 → 162,14
time_val = atoi(argv[i+1]);
sc_time opt_end_time(time_val,TIMESCALE_UNIT);
finish_time = opt_end_time;
//if (DEBUG_TRACESC) cout << "* Commmand line opt: Sim. will end at " << finish_time.to_string() << endl;
finish_time_set = 1;
}
//#if VM_TRACE
else if ( (strcmp(argv[i], "-f")==0) ||
(strcmp(argv[i], "--program")==0) )
{
do_program_file_load = 1; // Enable program loading - will be done after sim init
program_file = argv[i+1]; // Old char* style for program name
}
else if ( (strcmp(argv[i], "-s")==0) ||
(strcmp(argv[i], "--vcdstart")==0) )
{
170,7 → 176,6
time_val = atoi(argv[i+1]);
sc_time dump_start_time(time_val,TIMESCALE_UNIT);
dump_start = dump_start_time;
//if (DEBUG_TRACESC) cout << "* Commmand line opt: Dump start time set at " << dump_start.to_string() << endl;
dump_start_delay = 1;
dumping_now = 0;
}
180,25 → 185,26
time_val = atoi(argv[i+1]);
sc_time dump_stop_time(time_val,TIMESCALE_UNIT);
dump_stop = dump_stop_time;
//if (DEBUG_TRACESC) cout << "* Commmand line opt: Dump stop time set at " << dump_stop.to_string() << endl;
dump_stop_set = 1;
}
/* Depth setting of VCD doesn't appear to work, I think it's set during verilator script compile time */
/* Depth setting of VCD doesn't appear to work,
I think it's set during verilator script
compile time */
/* else if ( (strcmp(argv[i], "-p")==0) ||
(strcmp(argv[i], "--vcddepth")==0) )
{
dump_depth = atoi(argv[i+1]);
//if (DEBUG_TRACESC) cout << "* Commmand line opt: Dump depth set to " << dump_depth << endl;
}*/
(strcmp(argv[i], "--vcddepth")==0) )
{
dump_depth = atoi(argv[i+1]);
}*/
else if ( (strcmp(argv[i], "-h")==0) ||
(strcmp(argv[i], "--help")==0) )
{
printf("\n ORPSoC Cycle Accurate model usage:\n");
printf(" %s [-vh] [-d <file>] [-e <time>] [-s <time>] [-t <time>]",argv[0]);
printf(" %s [-vh] [-f <file] [-d <file>] [-e <time>] [-s <time>] [-t <time>]",argv[0]);
monitor->printSwitches();
printf("\n\n");
printf(" -h, --help\t\tPrint this help message\n");
printf(" -e, --endtime\t\tStop the sim at this time (ns)\n");
printf(" -f, --program\t\tLoad program from an OR32 ELF\n");
printf(" -v, --vcdon\t\tEnable VCD generation\n");
printf(" -d, --vcdfile\t\tEnable and specify target VCD file name\n");
 
307,8 → 313,21
// Init the UART function
uart->initUart(25000000, 115200);
 
SIM_RUNNING = 1;
if (do_program_file_load) // Did the user specify a file to load?
{
cout << "* Loading program from " << program_file << endl;
if (memoryload->loadcode(program_file,0,0) < 0)
{
cout << "* Error: executable file " << program_file << " not loaded" << endl;
}
}
else // Load SRAM from VMEM file
{
accessor->do_ram_readmemh();
}
 
SIM_RUNNING = 1;
// First check how we should run the sim.
if (VCD_enabled || finish_time_set)
{ // We'll run sim with step

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.