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

Subversion Repositories or1k

[/] [or1k/] [tags/] [nog_patch_47/] [or1ksim/] [cpu/] [or32/] [execute.c] - Diff between revs 1346 and 1350

Go to most recent revision | Show entire file | Details | Blame | View Log

Rev 1346 Rev 1350
Line 27... Line 27...
#include <stdio.h>
#include <stdio.h>
#include <string.h>
#include <string.h>
#include <ctype.h>
#include <ctype.h>
 
 
#include "config.h"
#include "config.h"
 
 
 
#ifdef HAVE_INTTYPES_H
 
#include <inttypes.h>
 
#endif
 
 
 
#include "port.h"
#include "arch.h"
#include "arch.h"
#include "branch_predict.h"
#include "branch_predict.h"
#include "abstract.h"
#include "abstract.h"
#include "labels.h"
#include "labels.h"
#include "parse.h"
#include "parse.h"
Line 44... Line 50...
#include "dmmu.h"
#include "dmmu.h"
#include "debug.h"
#include "debug.h"
#include "stats.h"
#include "stats.h"
 
 
/* General purpose registers. */
/* General purpose registers. */
machword reg[MAX_GPRS];
uorreg_t reg[MAX_GPRS];
 
 
/* Instruction queue */
/* Instruction queue */
struct iqueue_entry iqueue[20];
struct iqueue_entry iqueue[20];
 
 
/* Is current insn in execution a delay insn? */
/* Is current insn in execution a delay insn? */
Line 59... Line 65...
int issued_per_cycle = 4;
int issued_per_cycle = 4;
 
 
/* Whether break was hit - so we can step over a break */
/* Whether break was hit - so we can step over a break */
static int break_just_hit = 0;
static int break_just_hit = 0;
 
 
/* freemem 'pointer' */
 
extern unsigned long freemem;
 
 
 
/* Completition queue */
/* Completition queue */
struct iqueue_entry icomplet[20];
struct iqueue_entry icomplet[20];
 
 
/* Program counter (and translated PC) */
/* Program counter (and translated PC) */
unsigned long pc;
oraddr_t pc;
unsigned long pc_phy;
oraddr_t pc_phy;
 
 
/* Previous program counter */
/* Previous program counter */
unsigned long pcprev = 0;
oraddr_t pcprev = 0;
 
 
/* Temporary program counter */
/* Temporary program counter */
unsigned long pcnext;
oraddr_t pcnext;
 
 
/* Delay instruction effective address register */
/* Delay instruction effective address register */
unsigned long pcdelay;
oraddr_t pcdelay;
 
 
/* CCR */
/* CCR */
int flag;
int flag;
 
 
/* CCR (for dependency calculation) */
/* CCR (for dependency calculation) */
Line 104... Line 107...
static int next_delay_insn;
static int next_delay_insn;
static int breakpoint;
static int breakpoint;
 
 
/* Effective address of instructions that have an effective address.  This is
/* Effective address of instructions that have an effective address.  This is
 * only used to get dump_exe_log correct */
 * only used to get dump_exe_log correct */
static unsigned long insn_ea;
static oraddr_t insn_ea;
 
 
/* Implementation specific.
/* Implementation specific.
   Get an actual value of a specific register. */
   Get an actual value of a specific register. */
 
 
unsigned long evalsim_reg32(int regno)
uorreg_t evalsim_reg(unsigned int regno)
{
{
  if (regno < MAX_GPRS) {
  if (regno < MAX_GPRS) {
    return reg[regno];
    return reg[regno];
  } else {
  } else {
    PRINTF("\nABORT: read out of registers\n");
    PRINTF("\nABORT: read out of registers\n");
Line 123... Line 126...
}
}
 
 
/* Implementation specific.
/* Implementation specific.
   Set a specific register with value. */
   Set a specific register with value. */
 
 
void setsim_reg32(int regno, unsigned long value)
void setsim_reg(unsigned int regno, uorreg_t value)
{
{
  if (regno == 0)               /* gpr0 is always zero */
  if (regno == 0)               /* gpr0 is always zero */
    value = 0;
    value = 0;
 
 
  if (regno < MAX_GPRS) {
  if (regno < MAX_GPRS) {
Line 137... Line 140...
    runtime.sim.cont_run = 0;
    runtime.sim.cont_run = 0;
  }
  }
}
}
 
 
/* Implementation specific.
/* Implementation specific.
   Get an actual value of a specific register. */
 
 
 
inline static unsigned long eval_reg32(int regno)
 
{
 
  if (regno < MAX_GPRS) {
 
#if RAW_RANGE_STATS
 
      int delta = (runtime.sim.cycles - raw_stats.reg[regno]);
 
      if ((unsigned long)delta < (unsigned long)MAX_RAW_RANGE)
 
        raw_stats.range[delta]++;
 
#endif /* RAW_RANGE */
 
    return reg[regno];
 
  } else {
 
    PRINTF("\nABORT: read out of registers\n");
 
    runtime.sim.cont_run = 0;
 
    return 0;
 
  }
 
}
 
 
 
/* Implementation specific.
 
   Set a specific register with value. */
   Set a specific register with value. */
 
 
inline static void set_reg32(int regno, unsigned long value)
inline static void set_reg(int regno, uorreg_t value)
{
{
#if 0   
#if 0   
  if (strcmp(regstr, FRAME_REG) == 0) {
  if (strcmp(regstr, FRAME_REG) == 0) {
    PRINTF("FP (%s) modified by insn at %x. ", FRAME_REG, pc);
    PRINTF("FP (%s) modified by insn at %x. ", FRAME_REG, pc);
    PRINTF("Old:%.8lx  New:%.8lx\n", eval_reg(regno), value);
    PRINTF("Old:%.8lx  New:%.8lx\n", eval_reg(regno), value);
  }
  }
 
 
  if (strcmp(regstr, STACK_REG) == 0) {
  if (strcmp(regstr, STACK_REG) == 0) {
    PRINTF("SP (%s) modified by insn at %x. ", STACK_REG, pc);
    PRINTF("SP (%s) modified by insn at %x. ", STACK_REG, pc);
    PRINTF("Old:%.8lx  New:%.8lx\n", eval_reg(regmo), value);
    PRINTF("Old:%.8lx  New:%.8lx\n", eval_reg(regno), value);
  }
  }
#endif
#endif
 
 
  if (regno < MAX_GPRS) {
  if (regno < MAX_GPRS) {
    reg[regno] = value;
    reg[regno] = value;
Line 186... Line 170...
}
}
 
 
/* Implementation specific.
/* Implementation specific.
   Evaluates source operand opd. */
   Evaluates source operand opd. */
 
 
static unsigned long eval_operand_val(unsigned long insn,
static uorreg_t eval_operand_val(uint32_t insn, struct insn_op_struct *opd)
                                      struct insn_op_struct *opd)
 
{
{
  unsigned long operand = 0;
  unsigned long operand = 0;
  unsigned long sbit;
  unsigned long sbit;
  unsigned int nbits = 0;
  unsigned int nbits = 0;
 
 
Line 204... Line 187...
    opd++;
    opd++;
  }
  }
 
 
  if(opd->type & OPTYPE_SIG) {
  if(opd->type & OPTYPE_SIG) {
    sbit = (opd->type & OPTYPE_SBIT) >> OPTYPE_SBIT_SHR;
    sbit = (opd->type & OPTYPE_SBIT) >> OPTYPE_SBIT_SHR;
    if(operand & (1 << sbit)) operand |= 0xffffffff << sbit;
    if(operand & (1 << sbit)) operand |= ~REG_C(0) << sbit;
  }
  }
 
 
  return operand;
  return operand;
}
}
 
 
Line 230... Line 213...
     struct iqueue_entry *next;
     struct iqueue_entry *next;
{
{
  /* Find destination type. */
  /* Find destination type. */
  unsigned long type = 0;
  unsigned long type = 0;
  int prev_dis, next_dis;
  int prev_dis, next_dis;
  unsigned int prev_reg_val = 0;
  orreg_t prev_reg_val = 0;
  struct insn_op_struct *opd;
  struct insn_op_struct *opd;
 
 
  if (or32_opcodes[prev->insn_index].flags & OR32_W_FLAG
  if (or32_opcodes[prev->insn_index].flags & OR32_W_FLAG
      && or32_opcodes[next->insn_index].flags & OR32_R_FLAG)
      && or32_opcodes[next->insn_index].flags & OR32_R_FLAG)
    return 1;
    return 1;
Line 317... Line 300...
      break_just_hit = 1;
      break_just_hit = 1;
      return 1; /* Breakpoint set. */
      return 1; /* Breakpoint set. */
    }
    }
    break_just_hit = 0;
    break_just_hit = 0;
  }
  }
  pc_phy &= ~0x03;
  pc_phy &= ~ADDR_C(0x3);
 
 
  runtime.cpu.instructions++;
  runtime.cpu.instructions++;
 
 
  /* Fetch instruction. */
  /* Fetch instruction. */
  iqueue[0].insn_addr = pc;
  iqueue[0].insn_addr = pc;
Line 476... Line 459...
}
}
 
 
/* Outputs dissasembled instruction */
/* Outputs dissasembled instruction */
void dump_exe_log ()
void dump_exe_log ()
{
{
  unsigned long insn_addr = iqueue[0].insn_addr;
  oraddr_t insn_addr = iqueue[0].insn_addr;
  unsigned long i, j;
  unsigned int i, j;
 
  uorreg_t operand;
 
 
  if (insn_addr == 0xffffffff) return;
  if (insn_addr == 0xffffffff) return;
  if ((config.sim.exe_log_start <= runtime.cpu.instructions) &&
  if ((config.sim.exe_log_start <= runtime.cpu.instructions) &&
      ((config.sim.exe_log_end <= 0) ||
      ((config.sim.exe_log_end <= 0) ||
       (runtime.cpu.instructions <= config.sim.exe_log_end))) {
       (runtime.cpu.instructions <= config.sim.exe_log_end))) {
Line 489... Line 473...
        !(runtime.cpu.instructions % config.sim.exe_log_marker)) {
        !(runtime.cpu.instructions % config.sim.exe_log_marker)) {
      fprintf (runtime.sim.fexe_log, "--------------------- %8lli instruction ---------------------\n", runtime.cpu.instructions);
      fprintf (runtime.sim.fexe_log, "--------------------- %8lli instruction ---------------------\n", runtime.cpu.instructions);
    }
    }
    switch (config.sim.exe_log_type) {
    switch (config.sim.exe_log_type) {
    case EXE_LOG_HARDWARE:
    case EXE_LOG_HARDWARE:
      fprintf (runtime.sim.fexe_log, "\nEXECUTED(%11llu): %.8lx:  ",
      fprintf (runtime.sim.fexe_log, "\nEXECUTED(%11llu): %"PRIxADDR":  ",
               runtime.cpu.instructions, insn_addr);
               runtime.cpu.instructions, insn_addr);
      fprintf (runtime.sim.fexe_log, "%.2x%.2x", evalsim_mem8_void(insn_addr),
      fprintf (runtime.sim.fexe_log, "%.2x%.2x", evalsim_mem8_void(insn_addr),
               evalsim_mem8_void(insn_addr + 1));
               evalsim_mem8_void(insn_addr + 1));
      fprintf (runtime.sim.fexe_log, "%.2x%.2x",
      fprintf (runtime.sim.fexe_log, "%.2x%.2x",
               evalsim_mem8_void(insn_addr + 2),
               evalsim_mem8_void(insn_addr + 2),
               evalsim_mem8_void(insn_addr + 3));
               evalsim_mem8_void(insn_addr + 3));
      for(i = 0; i < MAX_GPRS; i++) {
      for(i = 0; i < MAX_GPRS; i++) {
        if (i % 4 == 0)
        if (i % 4 == 0)
          fprintf(runtime.sim.fexe_log, "\n");
          fprintf(runtime.sim.fexe_log, "\n");
        fprintf (runtime.sim.fexe_log, "GPR%2lu: %.8lx  ", i, reg[i]);
        fprintf (runtime.sim.fexe_log, "GPR%2u: %"PRIxREG"  ", i, reg[i]);
      }
      }
      fprintf (runtime.sim.fexe_log, "\n");
      fprintf (runtime.sim.fexe_log, "\n");
      fprintf (runtime.sim.fexe_log, "SR   : %.8lx  ", mfspr(SPR_SR));
      fprintf (runtime.sim.fexe_log, "SR   : %.8lx  ", mfspr(SPR_SR));
      fprintf (runtime.sim.fexe_log, "EPCR0: %.8lx  ", mfspr(SPR_EPCR_BASE));
      fprintf (runtime.sim.fexe_log, "EPCR0: %.8lx  ", mfspr(SPR_EPCR_BASE));
      fprintf (runtime.sim.fexe_log, "EEAR0: %.8lx  ", mfspr(SPR_EEAR_BASE));
      fprintf (runtime.sim.fexe_log, "EEAR0: %.8lx  ", mfspr(SPR_EEAR_BASE));
Line 524... Line 508...
        if (config.sim.exe_log_type == EXE_LOG_SOFTWARE) {
        if (config.sim.exe_log_type == EXE_LOG_SOFTWARE) {
          struct insn_op_struct *opd = op_start[iqueue[0].insn_index];
          struct insn_op_struct *opd = op_start[iqueue[0].insn_index];
 
 
          j = 0;
          j = 0;
          while (1) {
          while (1) {
            i = eval_operand_val (iqueue[0].insn, opd);
            operand = eval_operand_val (iqueue[0].insn, opd);
            while (!(opd->type & OPTYPE_OP))
            while (!(opd->type & OPTYPE_OP))
              opd++;
              opd++;
            if (opd->type & OPTYPE_DIS) {
            if (opd->type & OPTYPE_DIS) {
              fprintf (runtime.sim.fexe_log, "EA =%08lx PA =%08lx ", insn_ea,
              fprintf (runtime.sim.fexe_log, "EA =%"PRIxADDR" PA =%"PRIxADDR" ",
                       peek_into_dtlb(insn_ea,0,0));
                       insn_ea, peek_into_dtlb(insn_ea,0,0));
              opd++; /* Skip of register operand */
              opd++; /* Skip of register operand */
              j++;
              j++;
            } else if ((opd->type & OPTYPE_REG) && i) {
            } else if ((opd->type & OPTYPE_REG) && operand) {
              fprintf (runtime.sim.fexe_log, "r%-2li=%08lx ", i,
              fprintf (runtime.sim.fexe_log, "r%-2i=%"PRIxREG" ",
                       evalsim_reg32 (i));
                       (int)operand, evalsim_reg (operand));
            } else
            } else
              fprintf (runtime.sim.fexe_log, "             ");
              fprintf (runtime.sim.fexe_log, "             ");
            j++;
            j++;
            if(opd->type & OPTYPE_LAST)
            if(opd->type & OPTYPE_LAST)
              break;
              break;
Line 547... Line 531...
          while(j < 3) {
          while(j < 3) {
            fprintf (runtime.sim.fexe_log, "             ");
            fprintf (runtime.sim.fexe_log, "             ");
            j++;
            j++;
          }
          }
        }
        }
        fprintf (runtime.sim.fexe_log, "%.8lx ", insn_addr);
        fprintf (runtime.sim.fexe_log, "%"PRIxADDR" ", insn_addr);
        fprintf (runtime.sim.fexe_log, "%s\n", disassembled);
        fprintf (runtime.sim.fexe_log, "%s\n", disassembled);
      }
      }
    }
    }
  }
  }
}
}
 
 
/* Dump registers - 'r' or 't' command */
/* Dump registers - 'r' or 't' command */
void dumpreg()
void dumpreg()
{
{
  int i;
  int i;
  unsigned long physical_pc;
  oraddr_t physical_pc;
 
 
  if ((physical_pc = peek_into_itlb(iqueue[0].insn_addr))) {
  if ((physical_pc = peek_into_itlb(iqueue[0].insn_addr))) {
    /*
    /*
     * PRINTF("\t\t\tEA: %08x <--> PA: %08x\n", iqueue[0].insn_addr, physical_pc);
     * PRINTF("\t\t\tEA: %08x <--> PA: %08x\n", iqueue[0].insn_addr, physical_pc);
     */
     */
Line 572... Line 556...
    PRINTF("INTERNAL SIMULATOR ERROR:\n");
    PRINTF("INTERNAL SIMULATOR ERROR:\n");
    PRINTF("no translation for currently executed instruction\n");
    PRINTF("no translation for currently executed instruction\n");
  }
  }
 
 
  // generate_time_pretty (temp, runtime.sim.cycles * config.sim.clkcycle_ps);
  // generate_time_pretty (temp, runtime.sim.cycles * config.sim.clkcycle_ps);
  PRINTF(" (executed) [cycle %lld, #%lld]\n", runtime.sim.cycles, runtime.cpu.instructions);
  PRINTF(" (executed) [cycle %lld, #%lld]\n", runtime.sim.cycles,
 
         runtime.cpu.instructions);
  if (config.cpu.superscalar)
  if (config.cpu.superscalar)
    PRINTF ("Superscalar CYCLES: %u", runtime.cpu.supercycles);
    PRINTF ("Superscalar CYCLES: %u", runtime.cpu.supercycles);
  if (config.cpu.hazards)
  if (config.cpu.hazards)
    PRINTF ("  HAZARDWAIT: %u\n", runtime.cpu.hazardwait);
    PRINTF ("  HAZARDWAIT: %u\n", runtime.cpu.hazardwait);
  else
  else
Line 588... Line 573...
     * PRINTF("\t\t\tEA: %08x <--> PA: %08x\n", pc, physical_pc);
     * PRINTF("\t\t\tEA: %08x <--> PA: %08x\n", pc, physical_pc);
     */
     */
    dumpmemory(physical_pc, physical_pc + 4, 1, 0);
    dumpmemory(physical_pc, physical_pc + 4, 1, 0);
  }
  }
  else
  else
    PRINTF("%08lx: : xxxxxxxx  ITLB miss follows", pc);
    PRINTF("%"PRIxADDR": : xxxxxxxx  ITLB miss follows", pc);
 
 
  PRINTF(" (next insn) %s", (delay_insn?"(delay insn)":""));
  PRINTF(" (next insn) %s", (delay_insn?"(delay insn)":""));
  for(i = 0; i < MAX_GPRS; i++) {
  for(i = 0; i < MAX_GPRS; i++) {
    if (i % 4 == 0)
    if (i % 4 == 0)
      PRINTF("\n");
      PRINTF("\n");
    PRINTF("GPR%.2u: %.8lx  ", i, evalsim_reg32(i));
    PRINTF("GPR%.2u: %"PRIxREG"  ", i, evalsim_reg(i));
  }
  }
  PRINTF("flag: %u\n", flag);
  PRINTF("flag: %u\n", flag);
}
}
 
 
/* Generated/built in decoding/executing function */
/* Generated/built in decoding/executing function */
Line 638... Line 623...
  runtime.sim.storecycles = 0;
  runtime.sim.storecycles = 0;
  runtime.cpu.instructions = 0;
  runtime.cpu.instructions = 0;
  runtime.cpu.supercycles = 0;
  runtime.cpu.supercycles = 0;
  runtime.cpu.hazardwait = 0;
  runtime.cpu.hazardwait = 0;
  for (i = 0; i < MAX_GPRS; i++)
  for (i = 0; i < MAX_GPRS; i++)
    set_reg32 (i, 0);
    set_reg (i, 0);
  memset(iqueue, 0, sizeof(iqueue));
  memset(iqueue, 0, sizeof(iqueue));
  memset(icomplet, 0, sizeof(icomplet));
  memset(icomplet, 0, sizeof(icomplet));
 
 
  sbuf_head = 0;
  sbuf_head = 0;
  sbuf_tail = 0;
  sbuf_tail = 0;
Line 654... Line 639...
  setsprbits(SPR_VR, SPR_VR_VER, config.cpu.ver);
  setsprbits(SPR_VR, SPR_VR_VER, config.cpu.ver);
  setsprbits(SPR_VR, SPR_VR_REV, config.cpu.rev);
  setsprbits(SPR_VR, SPR_VR_REV, config.cpu.rev);
  mtspr(SPR_SR, config.cpu.sr);
  mtspr(SPR_SR, config.cpu.sr);
 
 
  pcnext = 0x0; /* MM1409: All programs should start at reset vector entry!  */
  pcnext = 0x0; /* MM1409: All programs should start at reset vector entry!  */
  if (config.sim.verbose) PRINTF ("Starting at 0x%08lx\n", pcnext);
  if (config.sim.verbose) PRINTF ("Starting at 0x%"PRIxADDR"\n", pcnext);
  pc = pcnext;
  pc = pcnext;
  pc_phy = pc;
  pc_phy = pc;
  pcnext += 4;
  pcnext += 4;
  debug(1, "reset ...\n");
  debug(1, "reset ...\n");
 
 
Line 697... Line 682...
 
 
 
 
#define INSTRUCTION(name) void name (struct iqueue_entry *current)
#define INSTRUCTION(name) void name (struct iqueue_entry *current)
 
 
/* Implementation specific.
/* Implementation specific.
 
   Get an actual value of a specific register. */
 
 
 
static uorreg_t eval_reg(unsigned int regno)
 
{
 
  if (regno < MAX_GPRS) {
 
#if RAW_RANGE_STATS
 
      int delta = (runtime.sim.cycles - raw_stats.reg[regno]);
 
      if ((unsigned long)delta < (unsigned long)MAX_RAW_RANGE)
 
        raw_stats.range[delta]++;
 
#endif /* RAW_RANGE */
 
    return reg[regno];
 
  } else {
 
    PRINTF("\nABORT: read out of registers\n");
 
    runtime.sim.cont_run = 0;
 
    return 0;
 
  }
 
}
 
 
 
/* Implementation specific.
   Evaluates source operand op_no. */
   Evaluates source operand op_no. */
 
 
static unsigned long eval_operand (int op_no, unsigned long insn_index,
static uorreg_t eval_operand (int op_no, unsigned long insn_index, uint32_t insn)
                                   unsigned long insn)
 
{
{
  struct insn_op_struct *opd = op_start[insn_index];
  struct insn_op_struct *opd = op_start[insn_index];
  unsigned long ret;
  uorreg_t ret;
 
 
  while (op_no) {
  while (op_no) {
    if(opd->type & OPTYPE_LAST) {
    if(opd->type & OPTYPE_LAST) {
      fprintf (stderr, "Instruction requested more operands than it has\n");
      fprintf (stderr, "Instruction requested more operands than it has\n");
      exit (1);
      exit (1);
Line 720... Line 723...
  if (opd->type & OPTYPE_DIS) {
  if (opd->type & OPTYPE_DIS) {
    ret = eval_operand_val (insn, opd);
    ret = eval_operand_val (insn, opd);
    while (!(opd->type & OPTYPE_OP))
    while (!(opd->type & OPTYPE_OP))
      opd++;
      opd++;
    opd++;
    opd++;
    ret += eval_reg32 (eval_operand_val (insn, opd));
    ret += eval_reg (eval_operand_val (insn, opd));
    insn_ea = ret;
    insn_ea = ret;
    return ret;
    return ret;
  }
  }
  if (opd->type & OPTYPE_REG)
  if (opd->type & OPTYPE_REG)
    return eval_reg32 (eval_operand_val (insn, opd));
    return eval_reg (eval_operand_val (insn, opd));
 
 
  return eval_operand_val (insn, opd);
  return eval_operand_val (insn, opd);
}
}
 
 
/* Implementation specific.
/* Implementation specific.
   Set destination operand (reister direct) with value. */
   Set destination operand (reister direct) with value. */
 
 
inline static void set_operand(int op_no, unsigned long value,
inline static void set_operand(int op_no, orreg_t value,
                               unsigned long insn_index, unsigned long insn)
                               unsigned long insn_index, uint32_t insn)
{
{
  struct insn_op_struct *opd = op_start[insn_index];
  struct insn_op_struct *opd = op_start[insn_index];
 
 
  while (op_no) {
  while (op_no) {
    if(opd->type & OPTYPE_LAST) {
    if(opd->type & OPTYPE_LAST) {
Line 752... Line 755...
 
 
  if (!(opd->type & OPTYPE_REG)) {
  if (!(opd->type & OPTYPE_REG)) {
    fprintf (stderr, "Trying to set a non-register operand\n");
    fprintf (stderr, "Trying to set a non-register operand\n");
    exit (1);
    exit (1);
  }
  }
  set_reg32 (eval_operand_val (insn, opd), value);
  set_reg (eval_operand_val (insn, opd), value);
}
}
 
 
/* Simple and rather slow decoding function based on built automata. */
/* Simple and rather slow decoding function based on built automata. */
static inline void decode_execute (struct iqueue_entry *current)
static inline void decode_execute (struct iqueue_entry *current)
{
{

powered by: WebSVN 2.1.0

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