URL
https://opencores.org/ocsvn/or1k_old/or1k_old/trunk
Subversion Repositories or1k_old
[/] [or1k_old/] [trunk/] [or1ksim/] [peripheral/] [mc.c] - Rev 1359
Go to most recent revision | Compare with Previous | Blame | View Log
/* mc.c -- Simulation of Memory Controller Copyright (C) 2001 by Marko Mlinar, markom@opencores.org This file is part of 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 2 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, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* Enable memory controller, via: section mc enable = 1 POC = 0x13243545 end Limitations: - memory refresh is not simulated */ #include <string.h> #include "config.h" #ifdef HAVE_INTTYPES_H #include <inttypes.h> #endif #include "port.h" #include "arch.h" #include "mc.h" #include "abstract.h" #include "sim-config.h" #include "debug.h" extern struct dev_memarea *dev_list; static struct mc mc; void set_csc_tms (int cs, unsigned long csc, unsigned long tms) { struct dev_memarea *mem_dev = dev_list; while (mem_dev) { if (mem_dev->chip_select == cs) { mem_dev->addr_mask = mc.ba_mask << 22; mem_dev->addr_compare = ((csc >> MC_CSC_SEL_OFFSET) /* & 0xff*/) << 22; mem_dev->valid = (csc >> MC_CSC_EN_OFFSET) & 0x01; if ((csc >> MC_CSC_MEMTYPE_OFFSET) && 0x07 == MC_CSC_MEMTYPE_ASYNC) { mem_dev->delayr = (tms & 0xff) + ((tms >> 8) & 0x0f); mem_dev->delayw = ((tms >> 12) & 0x0f) + ((tms >> 16) & 0x0f) + ((tms >> 20) & 0x3f); } else if ((csc >> MC_CSC_MEMTYPE_OFFSET) && 0x07 == MC_CSC_MEMTYPE_SDRAM) { mem_dev->delayr = 3 + ((tms >> 4) & 0x03); mem_dev->delayw = 3 + ((tms >> 4) & 0x03); } else if ((csc >> MC_CSC_MEMTYPE_OFFSET) && 0x07 == MC_CSC_MEMTYPE_SSRAM) { mem_dev->delayr = 2; mem_dev->delayw = 2; } else if ((csc >> MC_CSC_MEMTYPE_OFFSET) && 0x07 == MC_CSC_MEMTYPE_SYNC) { mem_dev->delayr = 2; mem_dev->delayw = 2; } return; } mem_dev = mem_dev->next; } } /* Set a specific MC register with value. */ void mc_write_word(oraddr_t addr, uint32_t value, void *dat) { int chipsel; debug(5, "mc_write_word(%"PRIxADDR",%08"PRIx32")\n", addr, value); addr -= config.mc.baseaddr; switch (addr) { case MC_CSR: mc.csr = value; break; case MC_POC: fprintf (stderr, "warning: write to MC's POC register!"); break; case MC_BA_MASK: mc.ba_mask = value & MC_BA_MASK_VALID; for (chipsel = 0; chipsel < N_CE; chipsel++) set_csc_tms (chipsel, mc.csc[chipsel], mc.tms[chipsel]); break; default: if (addr >= MC_CSC(0) && addr <= MC_TMS(N_CE - 1)) { addr -= MC_CSC(0); if ((addr >> 2) & 1) mc.tms[addr >> 3] = value; else mc.csc[addr >> 3] = value; set_csc_tms (addr >> 3, mc.csc[addr >> 3], mc.tms[addr >> 3]); break; } else debug(1, "write out of range (addr %"PRIxADDR")\n", addr + config.mc.baseaddr); } } /* Read a specific MC register. */ uint32_t mc_read_word(oraddr_t addr, void *dat) { uint32_t value = 0; debug(5, "mc_read_word(%"PRIxADDR")", addr); addr -= config.mc.baseaddr; switch (addr) { case MC_CSR: value = mc.csr; break; case MC_POC: value = mc.poc; break; case MC_BA_MASK: value = mc.ba_mask; break; default: if (addr >= MC_CSC(0) && addr <= MC_TMS(N_CE - 1)) { addr -= MC_CSC(0); if ((addr >> 2) & 1) value = mc.tms[addr >> 3]; else value = mc.csc[addr >> 3]; } else debug(1, " read out of range (addr %"PRIxADDR")\n", addr + config.mc.baseaddr); break; } debug(5, " value(%"PRIx32")\n", value); return value; } /* Read POC register and init memory controler regs. */ void mc_reset() { struct dev_memarea *mem_dev = dev_list; if (config.mc.enabled) { PRINTF("Resetting memory controller.\n"); memset(&mc, 0, sizeof(struct mc)); mc.poc = config.mc.POC; /* Set CS0 */ mc.csc[0] = (((config.mc.POC & 0x0c) >> 2) << MC_CSC_MEMTYPE_OFFSET) | ((config.mc.POC & 0x03) << MC_CSC_BW_OFFSET) | 1; if ((mc.csc[0] >> MC_CSC_MEMTYPE_OFFSET) && 0x07 == MC_CSC_MEMTYPE_ASYNC) { mc.tms[0] = MC_TMS_ASYNC_VALID; } else if ((mc.csc[0] >> MC_CSC_MEMTYPE_OFFSET) && 0x07 == MC_CSC_MEMTYPE_SDRAM) { mc.tms[0] = MC_TMS_SDRAM_VALID; } else if ((mc.csc[0] >> MC_CSC_MEMTYPE_OFFSET) && 0x07 == MC_CSC_MEMTYPE_SSRAM) { mc.tms[0] = MC_TMS_SSRAM_VALID; } else if ((mc.csc[0] >> MC_CSC_MEMTYPE_OFFSET) && 0x07 == MC_CSC_MEMTYPE_SYNC) { mc.tms[0] = MC_TMS_SYNC_VALID; } while (mem_dev) { mem_dev->valid = 0; mem_dev = mem_dev->next; } set_csc_tms (0, mc.csc[0], mc.tms[0]); register_memoryarea(config.mc.baseaddr, MC_ADDR_SPACE, 4, 1, mc_read_word, mc_write_word, NULL); } } inline void mc_clock() { } void mc_status() { int i; PRINTF( "\nMemory Controller at 0x%lX:\n", config.mc.baseaddr ); PRINTF( "POC: 0x%08lX\n", mc.poc ); PRINTF( "BAS: 0x%08lX\n", mc.ba_mask ); PRINTF( "CSR: 0x%08lX\n", mc.csr ); for (i=0; i<N_CE; i++) { PRINTF( "CE %02d - CSC: 0x%08lX TMS: 0x%08lX\n", i, mc.csc[i], mc.tms[i]); } } /*-----------------------------------------------------[ MC configuration }---*/ void mc_enabled(union param_val val, void *dat) { config.mc.enabled = val.int_val; } void mc_baseaddr(union param_val val, void *dat) { config.mc.baseaddr = val.addr_val; } void mc_POC(union param_val val, void *dat) { config.mc.POC = val.int_val; } void reg_mc_sec(void) { struct config_section *sec = reg_config_sec("mc", NULL, NULL); reg_config_param(sec, "enabled", paramt_int, mc_enabled); reg_config_param(sec, "baseaddr", paramt_addr, mc_baseaddr); reg_config_param(sec, "POC", paramt_int, mc_POC); }
Go to most recent revision | Compare with Previous | Blame | View Log