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

Subversion Repositories or1k

[/] [or1k/] [tags/] [nog_patch_69/] [or1ksim/] [peripheral/] [mc.c] - Diff between revs 1464 and 1765

Only display areas with differences | Details | Blame | View Log

Rev 1464 Rev 1765
/* mc.c -- Simulation of Memory Controller
/* mc.c -- Simulation of Memory Controller
         Copyright (C) 2001 by Marko Mlinar, markom@opencores.org
         Copyright (C) 2001 by Marko Mlinar, markom@opencores.org
 
 
         This file is part of OpenRISC 1000 Architectural Simulator.
         This file is part of OpenRISC 1000 Architectural Simulator.
 
 
         This program is free software; you can redistribute it and/or modify
         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
         it under the terms of the GNU General Public License as published by
         the Free Software Foundation; either version 2 of the License, or
         the Free Software Foundation; either version 2 of the License, or
         (at your option) any later version.
         (at your option) any later version.
 
 
         This program is distributed in the hope that it will be useful,
         This program is distributed in the hope that it will be useful,
         but WITHOUT ANY WARRANTY; without even the implied warranty of
         but WITHOUT ANY WARRANTY; without even the implied warranty of
         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.    See the
         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.    See the
         GNU General Public License for more details.
         GNU General Public License for more details.
 
 
         You should have received a copy of the GNU General Public License
         You should have received a copy of the GNU General Public License
         along with this program; if not, write to the Free Software
         along with this program; if not, write to the Free Software
         Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
         Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
*/
 
 
/* Enable memory controller, via:
/* Enable memory controller, via:
  section mc
  section mc
    enable = 1
    enable = 1
    POC = 0x13243545
    POC = 0x13243545
  end
  end
 
 
   Limitations:
   Limitations:
    - memory refresh is not simulated
    - memory refresh is not simulated
*/
*/
 
 
#include <string.h>
#include <string.h>
 
 
#include "config.h"
#include "config.h"
 
 
#ifdef HAVE_INTTYPES_H
#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#include <inttypes.h>
#endif
#endif
 
 
#include "port.h"
#include "port.h"
#include "arch.h"
#include "arch.h"
#include "mc.h"
#include "mc.h"
#include "abstract.h"
#include "abstract.h"
#include "sim-config.h"
#include "sim-config.h"
#include "debug.h"
#include "debug.h"
 
 
extern struct dev_memarea *dev_list;
extern struct dev_memarea *dev_list;
 
 
void set_csc_tms (int cs, unsigned long csc, unsigned long tms, struct mc *mc) {
void set_csc_tms (int cs, unsigned long csc, unsigned long tms, struct mc *mc) {
  struct dev_memarea *mem_dev = dev_list;
  struct dev_memarea *mem_dev = dev_list;
 
 
  while (mem_dev) {
  while (mem_dev) {
    if (mem_dev->chip_select == cs) {
    if (mem_dev->chip_select == cs) {
      mem_dev->addr_mask = mc->ba_mask << 22;
      mem_dev->addr_mask = mc->ba_mask << 22;
      mem_dev->addr_compare = ((csc >> MC_CSC_SEL_OFFSET) /* & 0xff*/) << 22;
      mem_dev->addr_compare = ((csc >> MC_CSC_SEL_OFFSET) /* & 0xff*/) << 22;
      mem_dev->valid = (csc >> MC_CSC_EN_OFFSET) & 0x01;
      mem_dev->valid = (csc >> MC_CSC_EN_OFFSET) & 0x01;
 
 
      if ((csc >> MC_CSC_MEMTYPE_OFFSET) && 0x07 == MC_CSC_MEMTYPE_ASYNC) {
      if ((csc >> MC_CSC_MEMTYPE_OFFSET) && 0x07 == MC_CSC_MEMTYPE_ASYNC) {
        mem_dev->delayr = (tms & 0xff) + ((tms >> 8) & 0x0f);
        mem_dev->delayr = (tms & 0xff) + ((tms >> 8) & 0x0f);
        mem_dev->delayw = ((tms >> 12)  & 0x0f) + ((tms >> 16) & 0x0f) + ((tms >> 20) & 0x3f);
        mem_dev->delayw = ((tms >> 12)  & 0x0f) + ((tms >> 16) & 0x0f) + ((tms >> 20) & 0x3f);
      } else if ((csc >> MC_CSC_MEMTYPE_OFFSET) && 0x07 == MC_CSC_MEMTYPE_SDRAM) {
      } else if ((csc >> MC_CSC_MEMTYPE_OFFSET) && 0x07 == MC_CSC_MEMTYPE_SDRAM) {
        mem_dev->delayr = 3 + ((tms >> 4) & 0x03);
        mem_dev->delayr = 3 + ((tms >> 4) & 0x03);
        mem_dev->delayw = 3 + ((tms >> 4) & 0x03);
        mem_dev->delayw = 3 + ((tms >> 4) & 0x03);
      } else if ((csc >> MC_CSC_MEMTYPE_OFFSET) && 0x07 == MC_CSC_MEMTYPE_SSRAM) {
      } else if ((csc >> MC_CSC_MEMTYPE_OFFSET) && 0x07 == MC_CSC_MEMTYPE_SSRAM) {
        mem_dev->delayr = 2;
        mem_dev->delayr = 2;
        mem_dev->delayw = 2;
        mem_dev->delayw = 2;
      } else if ((csc >> MC_CSC_MEMTYPE_OFFSET) && 0x07 == MC_CSC_MEMTYPE_SYNC) {
      } else if ((csc >> MC_CSC_MEMTYPE_OFFSET) && 0x07 == MC_CSC_MEMTYPE_SYNC) {
        mem_dev->delayr = 2;
        mem_dev->delayr = 2;
        mem_dev->delayw = 2;
        mem_dev->delayw = 2;
      }
      }
      return;
      return;
    }
    }
    mem_dev = mem_dev->next;
    mem_dev = mem_dev->next;
  }
  }
}
}
 
 
/* Set a specific MC register with value. */
/* Set a specific MC register with value. */
void mc_write_word(oraddr_t addr, uint32_t value, void *dat)
void mc_write_word(oraddr_t addr, uint32_t value, void *dat)
{
{
    struct mc *mc = dat;
    struct mc *mc = dat;
        int chipsel;
        int chipsel;
 
 
        debug(5, "mc_write_word(%"PRIxADDR",%08"PRIx32")\n", addr, value);
        debug(5, "mc_write_word(%"PRIxADDR",%08"PRIx32")\n", addr, value);
 
 
  addr -= mc->baseaddr;
  addr -= mc->baseaddr;
 
 
        switch (addr) {
        switch (addr) {
          case MC_CSR:
          case MC_CSR:
            mc->csr = value;
            mc->csr = value;
            break;
            break;
          case MC_POC:
          case MC_POC:
            fprintf (stderr, "warning: write to MC's POC register!");
            fprintf (stderr, "warning: write to MC's POC register!");
            break;
            break;
          case MC_BA_MASK:
          case MC_BA_MASK:
            mc->ba_mask = value & MC_BA_MASK_VALID;
            mc->ba_mask = value & MC_BA_MASK_VALID;
      for (chipsel = 0; chipsel < N_CE; chipsel++)
      for (chipsel = 0; chipsel < N_CE; chipsel++)
        set_csc_tms (chipsel, mc->csc[chipsel], mc->tms[chipsel], mc);
        set_csc_tms (chipsel, mc->csc[chipsel], mc->tms[chipsel], mc);
            break;
            break;
                default:
                default:
                  if (addr >= MC_CSC(0) && addr <= MC_TMS(N_CE - 1)) {
                  if (addr >= MC_CSC(0) && addr <= MC_TMS(N_CE - 1)) {
                    addr -= MC_CSC(0);
                    addr -= MC_CSC(0);
                    if ((addr >> 2) & 1)
                    if ((addr >> 2) & 1)
                      mc->tms[addr >> 3] = value;
                      mc->tms[addr >> 3] = value;
                    else
                    else
                      mc->csc[addr >> 3] = value;
                      mc->csc[addr >> 3] = value;
 
 
                    set_csc_tms (addr >> 3, mc->csc[addr >> 3], mc->tms[addr >> 3], mc);
                    set_csc_tms (addr >> 3, mc->csc[addr >> 3], mc->tms[addr >> 3], mc);
                    break;
                    break;
                  } else
                  } else
                        debug(1, "write out of range (addr %"PRIxADDR")\n", addr + mc->baseaddr);
                        debug(1, "write out of range (addr %"PRIxADDR")\n", addr + mc->baseaddr);
        }
        }
}
}
 
 
/* Read a specific MC register. */
/* Read a specific MC register. */
uint32_t mc_read_word(oraddr_t addr, void *dat)
uint32_t mc_read_word(oraddr_t addr, void *dat)
{
{
    struct mc *mc = dat;
    struct mc *mc = dat;
        uint32_t value = 0;
        uint32_t value = 0;
 
 
        debug(5, "mc_read_word(%"PRIxADDR")", addr);
        debug(5, "mc_read_word(%"PRIxADDR")", addr);
 
 
  addr -= mc->baseaddr;
  addr -= mc->baseaddr;
 
 
        switch (addr) {
        switch (addr) {
          case MC_CSR:
          case MC_CSR:
            value = mc->csr;
            value = mc->csr;
            break;
            break;
          case MC_POC:
          case MC_POC:
            value = mc->poc;
            value = mc->poc;
            break;
            break;
          case MC_BA_MASK:
          case MC_BA_MASK:
            value = mc->ba_mask;
            value = mc->ba_mask;
            break;
            break;
                default:
                default:
                  if (addr >= MC_CSC(0) && addr <= MC_TMS(N_CE - 1)) {
                  if (addr >= MC_CSC(0) && addr <= MC_TMS(N_CE - 1)) {
                    addr -= MC_CSC(0);
                    addr -= MC_CSC(0);
                    if ((addr >> 2) & 1)
                    if ((addr >> 2) & 1)
                      value = mc->tms[addr >> 3];
                      value = mc->tms[addr >> 3];
                    else
                    else
                      value = mc->csc[addr >> 3];
                      value = mc->csc[addr >> 3];
                  } else
                  } else
                        debug(1, " read out of range (addr %"PRIxADDR")\n", addr + mc->baseaddr);
                        debug(1, " read out of range (addr %"PRIxADDR")\n", addr + mc->baseaddr);
            break;
            break;
        }
        }
        debug(5, " value(%"PRIx32")\n", value);
        debug(5, " value(%"PRIx32")\n", value);
        return value;
        return value;
}
}
 
 
/* Read POC register and init memory controler regs. */
/* Read POC register and init memory controler regs. */
void mc_reset(void *dat)
void mc_reset(void *dat)
{
{
  struct mc *mc = dat;
  struct mc *mc = dat;
  struct dev_memarea *mem_dev = dev_list;
  struct dev_memarea *mem_dev = dev_list;
 
 
  PRINTF("Resetting memory controller.\n");
  PRINTF("Resetting memory controller.\n");
 
 
  memset(mc->csc, 0, sizeof(mc->csc));
  memset(mc->csc, 0, sizeof(mc->csc));
  memset(mc->tms, 0, sizeof(mc->tms));
  memset(mc->tms, 0, sizeof(mc->tms));
 
 
  mc->csr = 0;
  mc->csr = 0;
  mc->ba_mask = 0;
  mc->ba_mask = 0;
 
 
  /* Set CS0 */
  /* Set CS0 */
  mc->csc[0] = (((mc->poc & 0x0c) >> 2) << MC_CSC_MEMTYPE_OFFSET) | ((mc->poc & 0x03) << MC_CSC_BW_OFFSET) | 1;
  mc->csc[0] = (((mc->poc & 0x0c) >> 2) << MC_CSC_MEMTYPE_OFFSET) | ((mc->poc & 0x03) << MC_CSC_BW_OFFSET) | 1;
 
 
  if ((mc->csc[0] >> MC_CSC_MEMTYPE_OFFSET) && 0x07 == MC_CSC_MEMTYPE_ASYNC) {
  if ((mc->csc[0] >> MC_CSC_MEMTYPE_OFFSET) && 0x07 == MC_CSC_MEMTYPE_ASYNC) {
    mc->tms[0] = MC_TMS_ASYNC_VALID;
    mc->tms[0] = MC_TMS_ASYNC_VALID;
  } else if ((mc->csc[0] >> MC_CSC_MEMTYPE_OFFSET) && 0x07 == MC_CSC_MEMTYPE_SDRAM) {
  } else if ((mc->csc[0] >> MC_CSC_MEMTYPE_OFFSET) && 0x07 == MC_CSC_MEMTYPE_SDRAM) {
    mc->tms[0] = MC_TMS_SDRAM_VALID;
    mc->tms[0] = MC_TMS_SDRAM_VALID;
  } else if ((mc->csc[0] >> MC_CSC_MEMTYPE_OFFSET) && 0x07 == MC_CSC_MEMTYPE_SSRAM) {
  } else if ((mc->csc[0] >> MC_CSC_MEMTYPE_OFFSET) && 0x07 == MC_CSC_MEMTYPE_SSRAM) {
    mc->tms[0] = MC_TMS_SSRAM_VALID;
    mc->tms[0] = MC_TMS_SSRAM_VALID;
  } else if ((mc->csc[0] >> MC_CSC_MEMTYPE_OFFSET) && 0x07 == MC_CSC_MEMTYPE_SYNC) {
  } else if ((mc->csc[0] >> MC_CSC_MEMTYPE_OFFSET) && 0x07 == MC_CSC_MEMTYPE_SYNC) {
    mc->tms[0] = MC_TMS_SYNC_VALID;
    mc->tms[0] = MC_TMS_SYNC_VALID;
  }
  }
 
 
  while (mem_dev) {
  while (mem_dev) {
    mem_dev->valid = 0;
    mem_dev->valid = 0;
    mem_dev = mem_dev->next;
    mem_dev = mem_dev->next;
  }
  }
 
 
  set_csc_tms (0, mc->csc[0], mc->tms[0], mc);
  set_csc_tms (0, mc->csc[0], mc->tms[0], mc);
}
}
 
 
void mc_status(void *dat)
void mc_status(void *dat)
{
{
    struct mc *mc = dat;
    struct mc *mc = dat;
    int i;
    int i;
 
 
    PRINTF( "\nMemory Controller at 0x%"PRIxADDR":\n", mc->baseaddr );
    PRINTF( "\nMemory Controller at 0x%"PRIxADDR":\n", mc->baseaddr );
    PRINTF( "POC: 0x%08lX\n", mc->poc );
    PRINTF( "POC: 0x%08lX\n", mc->poc );
    PRINTF( "BAS: 0x%08lX\n", mc->ba_mask );
    PRINTF( "BAS: 0x%08lX\n", mc->ba_mask );
    PRINTF( "CSR: 0x%08lX\n", mc->csr );
    PRINTF( "CSR: 0x%08lX\n", mc->csr );
 
 
    for (i=0; i<N_CE; i++) {
    for (i=0; i<N_CE; i++) {
        PRINTF( "CE %02d -  CSC: 0x%08lX  TMS: 0x%08lX\n", i, mc->csc[i],
        PRINTF( "CE %02d -  CSC: 0x%08lX  TMS: 0x%08lX\n", i, mc->csc[i],
               mc->tms[i]);
               mc->tms[i]);
    }
    }
}
}
 
 
/*-----------------------------------------------------[ MC configuration }---*/
/*-----------------------------------------------------[ MC configuration }---*/
void mc_enabled(union param_val val, void *dat)
void mc_enabled(union param_val val, void *dat)
{
{
  struct mc *mc = dat;
  struct mc *mc = dat;
  mc->enabled = val.int_val;
  mc->enabled = val.int_val;
}
}
 
 
void mc_baseaddr(union param_val val, void *dat)
void mc_baseaddr(union param_val val, void *dat)
{
{
  struct mc *mc = dat;
  struct mc *mc = dat;
  mc->baseaddr = val.addr_val;
  mc->baseaddr = val.addr_val;
}
}
 
 
void mc_POC(union param_val val, void *dat)
void mc_POC(union param_val val, void *dat)
{
{
  struct mc *mc = dat;
  struct mc *mc = dat;
  mc->poc = val.int_val;
  mc->poc = val.int_val;
}
}
 
 
void *mc_sec_start(void)
void *mc_sec_start(void)
{
{
  struct mc *new = malloc(sizeof(struct mc));
  struct mc *new = malloc(sizeof(struct mc));
 
 
  if(!new) {
  if(!new) {
    fprintf(stderr, "Peripheral MC: Run out of memory\n");
    fprintf(stderr, "Peripheral MC: Run out of memory\n");
    exit(-1);
    exit(-1);
  }
  }
 
 
  new->enabled = 0;
  new->enabled = 0;
 
 
  return new;
  return new;
}
}
 
 
void mc_sec_end(void *dat)
void mc_sec_end(void *dat)
{
{
  struct mc *mc = dat;
  struct mc *mc = dat;
 
 
  if(!mc->enabled) {
  if(!mc->enabled) {
    free(dat);
    free(dat);
    return;
    return;
  }
  }
 
 
  register_memoryarea(mc->baseaddr, MC_ADDR_SPACE, 4, 1, mc_read_word,
  register_memoryarea(mc->baseaddr, MC_ADDR_SPACE, 4, 1, mc_read_word,
                      mc_write_word, dat);
                      mc_write_word, dat);
  reg_sim_reset(mc_reset, dat);
  reg_sim_reset(mc_reset, dat);
  reg_sim_stat(mc_status, dat);
  reg_sim_stat(mc_status, dat);
}
}
 
 
void reg_mc_sec(void)
void reg_mc_sec(void)
{
{
  struct config_section *sec = reg_config_sec("mc", mc_sec_start, mc_sec_end);
  struct config_section *sec = reg_config_sec("mc", mc_sec_start, mc_sec_end);
 
 
  reg_config_param(sec, "enabled", paramt_int, mc_enabled);
  reg_config_param(sec, "enabled", paramt_int, mc_enabled);
  reg_config_param(sec, "baseaddr", paramt_addr, mc_baseaddr);
  reg_config_param(sec, "baseaddr", paramt_addr, mc_baseaddr);
  reg_config_param(sec, "POC", paramt_int, mc_POC);
  reg_config_param(sec, "POC", paramt_int, mc_POC);
}
}
 
 

powered by: WebSVN 2.1.0

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