URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
[/] [or1k/] [tags/] [nog_patch_38/] [or1ksim/] [peripheral/] [mc.c] - Rev 1769
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; void set_csc_tms (int cs, unsigned long csc, unsigned long tms, struct mc *mc) { 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) { struct mc *mc = dat; int chipsel; debug(5, "mc_write_word(%"PRIxADDR",%08"PRIx32")\n", addr, value); addr -= 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], mc); 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], mc); break; } else debug(1, "write out of range (addr %"PRIxADDR")\n", addr + mc->baseaddr); } } /* Read a specific MC register. */ uint32_t mc_read_word(oraddr_t addr, void *dat) { struct mc *mc = dat; uint32_t value = 0; debug(5, "mc_read_word(%"PRIxADDR")", addr); addr -= 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 + mc->baseaddr); break; } debug(5, " value(%"PRIx32")\n", value); return value; } /* Read POC register and init memory controler regs. */ void mc_reset(void *dat) { struct mc *mc = dat; struct dev_memarea *mem_dev = dev_list; PRINTF("Resetting memory controller.\n"); memset(mc->csc, 0, sizeof(mc->csc)); memset(mc->tms, 0, sizeof(mc->tms)); mc->csr = 0; mc->ba_mask = 0; /* Set CS0 */ 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) { 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], mc); } void mc_status(void *dat) { struct mc *mc = dat; int i; PRINTF( "\nMemory Controller at 0x%"PRIxADDR":\n", 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) { struct mc *mc = dat; mc->enabled = val.int_val; } void mc_baseaddr(union param_val val, void *dat) { struct mc *mc = dat; mc->baseaddr = val.addr_val; } void mc_POC(union param_val val, void *dat) { struct mc *mc = dat; mc->poc = val.int_val; } void *mc_sec_start(void) { struct mc *new = malloc(sizeof(struct mc)); if(!new) { fprintf(stderr, "Peripheral MC: Run out of memory\n"); exit(-1); } new->enabled = 0; return new; } void mc_sec_end(void *dat) { struct mc *mc = dat; if(mc->enabled) { register_memoryarea(mc->baseaddr, MC_ADDR_SPACE, 4, 1, mc_read_word, mc_write_word, dat); reg_sim_reset(mc_reset, dat); reg_sim_stat(mc_status, dat); } } void reg_mc_sec(void) { 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, "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