|
View:
New views
18 Messages
—
Rating Filter:
Alert me
|
|
|
|
|
|
Re: Re: an1.pdf problem with step 7On Mon, 2009-02-23 at 14:29 +0000, Jeremy Bennett wrote:
> On Sun, 2009-02-22 at 23:49 +0000, Licínio Sousa wrote: > > > > I am trying to run step 7 of the AN1. > > It happens that after linking i run the example, the terminal starts > > but no echo appears in the terminal window. And no CHAR READ appear in > > the LOG. > > > > How strange. I've just checked and I have exactly the same result. I > will investigate further. I've investigated further. It's an endianism problem, which looks to have been introduced into the recent fixes to Or1ksim. I'm going to make the Or1ksim external interface explicitly host-endian (rather than model endian). This will be consistent with SystemC TLM 2.0 use where communication is always host-endian, whatever the endianness of the models at each end. This in turn requires all the EAN1 examples to be tidied up to work with host endianness (I think it only affects the UartSC class and sub-classes). It actually makes things rather simpler, since the UART is byte addressed anyway, so shouldn't be affected by endianness anyway. This needs a full new release. As a short-term fix, I've attached two files. First a rewritten generic.c for Or1ksim (goes in the peripheral directory). This uses functions htoml, htoms, mtohl and mtohs to convert between model and host endianess. Second an updated UartSC.cpp, which ignores the model endianness. Please let me know if this fixes the problem. You'll need to make corresponding changes in the UART classes for subsequent chapters. Updated release will follow shortly. ATB, Jeremy -- Tel: +44 (1202) 416955 Cell: +44 (7970) 676050 SkypeID: jeremybennett Email: jeremy.bennett@... Web: www.embecosm.com [generic.c] /* generic.c -- Generic external peripheral Copyright (C) 2008 Embecosm Limited Contributor Jeremy Bennett <jeremy.bennett@...> 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 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. */ /* This is functional simulation of any external peripheral. It's job is to * trap accesses in a specific range, so that the simulator can drive an * external device. * * A note on endianess. All external communication is done using HOST * endianess. A set of functions are provided to convert between host and * model endianess (htoml, htoms, mtohl, mtohs). */ /* Autoconf and/or portability configuration */ #include "config.h" /* System includes */ #include <stdlib.h> #include <stdio.h> /* Package includes */ #include "arch.h" #include "sim-config.h" #include "abstract.h" #include "toplevel-support.h" #include "sim-cmd.h" /*! State associated with the generic device. */ struct dev_generic { /* Info about a particular transaction */ enum { /* Direction of the access */ GENERIC_READ, GENERIC_WRITE } trans_direction; enum { /* Size of the access */ GENERIC_BYTE, GENERIC_HW, GENERIC_WORD } trans_size; uint32_t value; /* The value to read/write */ /* Configuration */ int enabled; /* Device enabled */ int byte_enabled; /* Byte R/W allowed */ int hw_enabled; /* Half word R/W allowed */ int word_enabled; /* Full word R/W allowed */ char *name; /* Name of the device */ oraddr_t baseaddr; /* Base address of device */ uint32_t size; /* Address space size (bytes) */ }; /* Convert a 32-bit value from host to model endianess */ static unsigned long int htoml (unsigned long int host_val) { unsigned char model_array[4]; #ifdef OR32_BIG_ENDIAN model_array[0] = (host_val >> 24) & 0xff; model_array[1] = (host_val >> 16) & 0xff; model_array[2] = (host_val >> 8) & 0xff; model_array[3] = (host_val ) & 0xff; #else model_array[0] = (host_val ) & 0xff; model_array[1] = (host_val >> 8) & 0xff; model_array[2] = (host_val >> 16) & 0xff; model_array[3] = (host_val >> 24) & 0xff; #endif return *((unsigned long int *)model_array); } /* htoml () */ /* Convert a 16-bit value from host to model endianess */ static unsigned short int htoms (unsigned short int host_val) { unsigned char model_array[2]; #ifdef OR32_BIG_ENDIAN model_array[0] = (host_val >> 8) & 0xff; model_array[1] = (host_val ) & 0xff; #else model_array[0] = (host_val ) & 0xff; model_array[1] = (host_val >> 8) & 0xff; #endif return *((unsigned short int *)model_array); } /* htoms () */ /* Convert a 32-bit value from model to host endianess */ static unsigned long int mtohl (unsigned long int model_val) { unsigned char *model_array = (unsigned char *)(&model_val); unsigned long int host_val; #ifdef OR32_BIG_ENDIAN host_val = model_array[0]; host_val = (host_val << 8) | model_array[1]; host_val = (host_val << 8) | model_array[2]; host_val = (host_val << 8) | model_array[3]; #else host_val = model_array[3]; host_val = (host_val << 8) | model_array[2]; host_val = (host_val << 8) | model_array[1]; host_val = (host_val << 8) | model_array[0]; #endif return host_val; } /* mtohl () */ /* Convert a 32-bit value from model to host endianess */ static unsigned short int mtohs (unsigned short int model_val) { unsigned char *model_array = (unsigned char *)(&model_val); unsigned short int host_val; #ifdef OR32_BIG_ENDIAN host_val = model_array[0]; host_val = (host_val << 8) | model_array[1]; #else host_val = model_array[1]; host_val = (host_val << 8) | model_array[0]; #endif return host_val; } /* mtohs () */ /* Generic read and write upcall routines. Note the address here is absolute, not relative to the device. The mask uses host endianess, not Or1ksim endianess. */ static unsigned long int ext_read (unsigned long int addr, unsigned long int mask) { return config.ext.read_up (config.ext.class_ptr, addr, mask); } /* ext_callback() */ /* Generic read and write upcall routines. Note the address here is absolute, not relative to the device. The mask and value use host endianess, not Or1ksim endianess. */ static void ext_write (unsigned long int addr, unsigned long int mask, unsigned long int value) { config.ext.write_up (config.ext.class_ptr, addr, mask, value); } /* ext_callback() */ /* I/O routines. Note that address is relative to start of address space. */ static uint8_t generic_read_byte (oraddr_t addr, void *dat) { struct dev_generic *dev = (struct dev_generic *) dat; if (!config.ext.class_ptr) { fprintf (stderr, "Byte read from disabled generic device\n"); return 0; } else if (addr >= dev->size) { fprintf (stderr, "Byte read out of range for generic device %s " "(addr %" PRIxADDR ")\n", dev->name, addr); return 0; } else { unsigned long fulladdr = (unsigned long int) (addr + dev->baseaddr); unsigned long wordaddr = fulladdr & 0xfffffffc; unsigned long bytenum = fulladdr & 0x00000003; uint8_t mask_array[4]; unsigned long res; uint8_t *res_array; /* This works whatever the host endianess */ memset (mask_array, 0, 4); mask_array[bytenum] = 0xff; res = ext_read (wordaddr, *((unsigned int *)mask_array)); res_array = (uint8_t *)(&res); return res_array[bytenum]; } } /* generic_read_byte() */ static void generic_write_byte (oraddr_t addr, uint8_t value, void *dat) { struct dev_generic *dev = (struct dev_generic *) dat; if (!config.ext.class_ptr) { fprintf (stderr, "Byte write to disabled generic device\n"); } else if (addr >= dev->size) { fprintf (stderr, "Byte written out of range for generic device %s " "(addr %" PRIxADDR ")\n", dev->name, addr); } else { unsigned long fulladdr = (unsigned long int) (addr + dev->baseaddr); unsigned long wordaddr = fulladdr & 0xfffffffc; unsigned long bytenum = fulladdr & 0x00000003; uint8_t mask_array[4]; uint8_t value_array[4]; /* This works whatever the host endianess */ memset (mask_array, 0, 4); mask_array[bytenum] = 0xff; memset (value_array, 0, 4); value_array[bytenum] = value; ext_write (wordaddr, *((unsigned long int *)mask_array), *((unsigned long int *)value_array)); } } /* generic_write_byte() */ /* Result is in model endianess */ static uint16_t generic_read_hw (oraddr_t addr, void *dat) { struct dev_generic *dev = (struct dev_generic *) dat; if (!config.ext.class_ptr) { fprintf (stderr, "Half word read from disabled generic device\n"); return 0; } else if (addr >= dev->size) { fprintf (stderr, "Half-word read out of range for generic device %s " "(addr %" PRIxADDR ")\n", dev->name, addr); return 0; } else if (addr & 0x1) { fprintf (stderr, "Unaligned half word read from 0x%" PRIxADDR " ignored\n", addr); return 0; } else { unsigned long fulladdr = (unsigned long int) (addr + dev->baseaddr); unsigned long wordaddr = fulladdr & 0xfffffffc; unsigned long bytenum = fulladdr & 0x00000002; uint8_t mask_array[4]; unsigned long res; uint8_t *res_array; uint8_t hwres_array[2]; /* This works whatever the host endianess */ memset (mask_array, 0, 4); mask_array[bytenum] = 0xff; mask_array[bytenum + 1] = 0xff; res = ext_read (wordaddr, *((unsigned int *)mask_array)); res_array = (uint8_t *)(&res); hwres_array[0] = res_array[bytenum]; hwres_array[1] = res_array[bytenum + 1]; return htoms (*((uint16_t *)hwres_array)); } } /* generic_read_hw() */ /* Value is in model endianness */ static void generic_write_hw (oraddr_t addr, uint16_t value, void *dat) { struct dev_generic *dev = (struct dev_generic *) dat; if (!config.ext.class_ptr) { fprintf (stderr, "Half word write to disabled generic device\n"); } else if (addr >= dev->size) { fprintf (stderr, "Half-word written out of range for generic device %s " "(addr %" PRIxADDR ")\n", dev->name, addr); } else if (addr & 0x1) { fprintf (stderr, "Unaligned half word write to 0x%" PRIxADDR " ignored\n", addr); } else { uint16_t host_value = mtohs (value); unsigned long fulladdr = (unsigned long int) (addr + dev->baseaddr); unsigned long wordaddr = fulladdr & 0xfffffffc; unsigned long bytenum = fulladdr & 0x00000002; uint8_t mask_array[4]; uint8_t value_array[4]; uint8_t *hw_value_array; /* This works whatever the host endianess */ memset (mask_array, 0, 4); mask_array[bytenum] = 0xff; mask_array[bytenum + 1] = 0xff; memset (value_array, 0, 4); hw_value_array = (uint8_t *)(&host_value); value_array[bytenum] = hw_value_array[0]; value_array[bytenum + 1] = hw_value_array[1]; ext_write (wordaddr, *((unsigned long int *)mask_array), *((unsigned long int *)value_array)); } } /* generic_write_hw() */ static uint32_t generic_read_word (oraddr_t addr, void *dat) { struct dev_generic *dev = (struct dev_generic *) dat; if (!config.ext.class_ptr) { fprintf (stderr, "Full word read from disabled generic device\n"); return 0; } else if (addr >= dev->size) { fprintf (stderr, "Full word read out of range for generic device %s " "(addr %" PRIxADDR ")\n", dev->name, addr); return 0; } else if (0 != (addr & 0x3)) { fprintf (stderr, "Unaligned full word read from 0x%" PRIxADDR " ignored\n", addr); return 0; } else { unsigned long wordaddr = (unsigned long int) (addr + dev->baseaddr); return (uint32_t) htoml (ext_read (wordaddr, 0xffffffff)); } } /* generic_read_word() */ static void generic_write_word (oraddr_t addr, uint32_t value, void *dat) { struct dev_generic *dev = (struct dev_generic *) dat; if (!config.ext.class_ptr) { fprintf (stderr, "Full word write to disabled generic device\n"); } else if (addr >= dev->size) { fprintf (stderr, "Full word written out of range for generic device %s " "(addr %" PRIxADDR ")\n", dev->name, addr); } else if (0 != (addr & 0x3)) { fprintf (stderr, "Unaligned full word write to 0x%" PRIxADDR " ignored\n", addr); } else { unsigned long host_value = mtohl (value); unsigned long wordaddr = (unsigned long int) (addr + dev->baseaddr); ext_write (wordaddr, 0xffffffff, host_value); } } /* generic_write_word() */ /* Reset is a null operation */ static void generic_reset (void *dat) { return; } /* generic_reset() */ /* Status report can only advise of configuration. */ static void generic_status (void *dat) { struct dev_generic *dev = (struct dev_generic *) dat; PRINTF ("\nGeneric device \"%s\" at 0x%" PRIxADDR ":\n", dev->name, dev->baseaddr); PRINTF (" Size 0x%" PRIx32 "\n", dev->size); if (dev->byte_enabled) { PRINTF (" Byte R/W enabled\n"); } if (dev->hw_enabled) { PRINTF (" Half word R/W enabled\n"); } if (dev->word_enabled) { PRINTF (" Full word R/W enabled\n"); } PRINTF ("\n"); } /* generic_status() */ /* Functions to set configuration */ static void generic_enabled (union param_val val, void *dat) { ((struct dev_generic *) dat)->enabled = val.int_val; } /* generic_enabled() */ static void generic_byte_enabled (union param_val val, void *dat) { ((struct dev_generic *) dat)->byte_enabled = val.int_val; } /* generic_byte_enabled() */ static void generic_hw_enabled (union param_val val, void *dat) { ((struct dev_generic *) dat)->hw_enabled = val.int_val; } /* generic_hw_enabled() */ static void generic_word_enabled (union param_val val, void *dat) { ((struct dev_generic *) dat)->word_enabled = val.int_val; } /* generic_word_enabled() */ static void generic_name (union param_val val, void *dat) { ((struct dev_generic *) dat)->name = strdup (val.str_val); if (!((struct dev_generic *) dat)->name) { fprintf (stderr, "Peripheral 16450: name \"%s\": Run out of memory\n", val.str_val); exit (-1); } } /* generic_name() */ static void generic_baseaddr (union param_val val, void *dat) { ((struct dev_generic *) dat)->baseaddr = val.addr_val; } /* generic_baseaddr() */ static void generic_size (union param_val val, void *dat) { ((struct dev_generic *) dat)->size = val.int_val; } /* generic_size() */ /* Start of new generic section */ static void * generic_sec_start () { struct dev_generic *new = (struct dev_generic *) malloc (sizeof (struct dev_generic)); if (0 == new) { fprintf (stderr, "Generic peripheral: Run out of memory\n"); exit (-1); } /* Default names */ new->enabled = 1; new->byte_enabled = 1; new->hw_enabled = 1; new->word_enabled = 1; new->name = "anonymous external peripheral"; new->baseaddr = 0; new->size = 0; return new; } /* generic_sec_start() */ /* End of new generic section */ static void generic_sec_end (void *dat) { struct dev_generic *generic = (struct dev_generic *) dat; struct mem_ops ops; /* Give up if not enabled, or if size is zero, or if no access size is enabled. */ if (!generic->enabled) { free (dat); return; } if (0 == generic->size) { fprintf (stderr, "Generic peripheral \"%s\" has size 0: ignoring", generic->name); free (dat); return; } if (!generic->byte_enabled && !generic->hw_enabled && !generic->word_enabled) { fprintf (stderr, "Generic peripheral \"%s\" has no access: ignoring", generic->name); free (dat); return; } /* Zero all the ops, then set the ones we care about. Read/write delays will * come from the peripheral if desired. */ memset (&ops, 0, sizeof (struct mem_ops)); if (generic->byte_enabled) { ops.readfunc8 = generic_read_byte; ops.writefunc8 = generic_write_byte; ops.read_dat8 = dat; ops.write_dat8 = dat; } if (generic->hw_enabled) { ops.readfunc16 = generic_read_hw; ops.writefunc16 = generic_write_hw; ops.read_dat16 = dat; ops.write_dat16 = dat; } if (generic->word_enabled) { ops.readfunc32 = generic_read_word; ops.writefunc32 = generic_write_word; ops.read_dat32 = dat; ops.write_dat32 = dat; } /* Register everything */ reg_mem_area (generic->baseaddr, generic->size, 0, &ops); reg_sim_reset (generic_reset, dat); reg_sim_stat (generic_status, dat); } /* generic_sec_end() */ /* Register a generic section. */ void reg_generic_sec (void) { struct config_section *sec = reg_config_sec ("generic", generic_sec_start, generic_sec_end); reg_config_param (sec, "enabled", paramt_int, generic_enabled); reg_config_param (sec, "byte_enabled", paramt_int, generic_byte_enabled); reg_config_param (sec, "hw_enabled", paramt_int, generic_hw_enabled); reg_config_param (sec, "word_enabled", paramt_int, generic_word_enabled); reg_config_param (sec, "name", paramt_str, generic_name); reg_config_param (sec, "baseaddr", paramt_addr, generic_baseaddr); reg_config_param (sec, "size", paramt_int, generic_size); } /* reg_generic_sec */ [UartSC.cpp] // ---------------------------------------------------------------------------- // Example Programs for "Building a Loosely Timed SoC Model with OSCI TLM 2.0" // Copyright (C) 2008 Embecosm Limited <info@...> // This program is free software: you can redistribute it and/or modify it // under the terms of the GNU Lesser 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 Lesser General Public // License for more details. // You should have received a copy of the GNU Lesser General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. // ---------------------------------------------------------------------------- // Implementation of 16450 UART SystemC module. // $Id: UartSC.cpp 86 2008-06-28 15:07:22Z jeremy $ #include <iostream> #include <iomanip> #include "UartSC.h" SC_HAS_PROCESS( UartSC ); //! Custom constructor for the UART module //! Passes the name to the parent constructor. Sets the model endianism //! (UartSC::isLittleEndian). //! Sets up threads listening to the bus (UartSC::busThread()) and the Rx pin //! (UartSC::rxThread()). //! Registers UartSC::busReadWrite() as the callback for blocking transport on //! the UartSC::bus socket. //! Zeros the registers, but leaves the UartSC::regs.dl unset - it is //! undefined until used. //! @param name The SystemC module name, passed to the parent //! constructor //! @param _isLittleEndian The model endianism UartSC::UartSC( sc_core::sc_module_name name, bool _isLittleEndian ) : sc_module( name ), isLittleEndian( _isLittleEndian ), intrPending( 0 ) { // Set up the thread for the bus side SC_THREAD( busThread ); // Set up the method for the terminal side (statically sensitive to Rx) SC_METHOD( rxMethod ); sensitive << rx; dont_initialize(); // Register the blocking transport method bus.register_b_transport( this, &UartSC::busReadWrite ); // Clear UART regs bzero( (void *)®s, sizeof( regs )); } /* UartSC() */ //! SystemC thread listening for transmit traffic on the bus //! Sits in a loop. Initially sets the line status register to indicate the //! buffer is empty (reset will clear these bits) and sends an interrupt (if //! enabled) to indicate the buffer is empty. //! Then waits for the UartSC::txReceived event to be triggered (this happens //! when new data is written into the transmit buffer by a bus write). //! On receipt of a character writes the char onto the Tx FIFO. void UartSC::busThread() { // Loop listening for changes on the Tx buffer, waiting for a baud rate // delay then sending to the terminal while( true ) { set( regs.lsr, UART_LSR_THRE ); // Indicate buffer empty set( regs.lsr, UART_LSR_TEMT ); genIntr( UART_IER_TBEI ); // Interrupt if enabled wait( txReceived ); // Wait for a Tx request tx.write( regs.thr ); // Send char to terminal } } // busThread() //! SystemC method sensitive to data on the Rx buffer //! Copies the character received into the read buffer. //! Sets the data ready flag of the line status register and sends an //! interrupt (if enabled) to indicate the data is ready. //! @note The terminal attached to the FIFO is responsible for modeling any //! wire delay on the Rx. void UartSC::rxMethod() { regs.rbr = rx.read(); sc_core::sc_time now = sc_core::sc_time_stamp(); printf( "Char '%c' read at %12.9f sec\n", regs.rbr, now.to_seconds()); set( regs.lsr, UART_LSR_DR ); // Mark data ready genIntr( UART_IER_RBFI ); // Interrupt if enabled } // rxMethod() //! TLM2.0 blocking transport routine for the UART bus socket //! Receives transport requests on the target socket. //! Break out the address, data and byte enable mask. All data is host endian, //! so we do not need to allow for Orksim model endianism in calculating this //! (see UartSC::isLittleEndian). //! Switches on the command and calls UartSC::busRead() or UartSC::buswrite() //! routines to do the behavior //! Increases the delay as appropriate and sets a success response. //! @param payload The transaction payload //! @param delay How far the initiator is beyond baseline SystemC time. For //! use with temporal decoupling. void UartSC::busReadWrite( tlm::tlm_generic_payload &payload, sc_core::sc_time &delay ) { // Break out the address, mask and data pointer. This should be only a // single byte access. sc_dt::uint64 addr = payload.get_address(); unsigned char *maskPtr = payload.get_byte_enable_ptr(); unsigned char *dataPtr = payload.get_data_ptr(); int offset; // Data byte offset in word unsigned char uaddr; // UART address // Deduce the byte address, allowing for endianism of the ISS switch( *((uint32_t *)maskPtr) ) { case 0x000000ff: offset = 0; break; case 0x0000ff00: offset = 1; break; case 0x00ff0000: offset = 2; break; case 0xff000000: offset = 3; break; default: // Invalid request payload.set_response_status( tlm::TLM_GENERIC_ERROR_RESPONSE ); return; } // Mask off the address to its range. This ought to have been done already // by an arbiter/decoder. uaddr = (unsigned char)((addr + offset) & UART_ADDR_MASK); // Which command? switch( payload.get_command() ) { case tlm::TLM_READ_COMMAND: dataPtr[offset] = busRead( uaddr ); break; case tlm::TLM_WRITE_COMMAND: busWrite( uaddr, dataPtr[offset] ); break; case tlm::TLM_IGNORE_COMMAND: payload.set_response_status( tlm::TLM_GENERIC_ERROR_RESPONSE ); return; } // Single byte accesses always work payload.set_response_status( tlm::TLM_OK_RESPONSE ); } // busReadWrite() //! Process a read on the UART bus //! Switch on the address to determine behavior //! - UART_BUF //! - if UART_LSR_DLAB is set, read the low byte of the clock divisor //! - otherwise get the value from the read buffer and //! clear the data ready flag in the line status register //! - UART_IER //! - if UART_LSR_DLAB is set, read the high byte of the clock divisor //! - otherwise get the instruction enable register //! - UART_IIR Get the interrupt indicator register and //! clear the most important pending interrupt (UartSC::clrIntr()) //! - UART_LCR Get the line control register //! - UART_MCR Ignored - write only register //! - UART_LSR Get the line status register //! - UART_MSR Get the modem status registe //! - UART_SCR Get the scratch register //! @param uaddr The address of the register being accessed //! @return The value read unsigned char UartSC::busRead( unsigned char uaddr ) { unsigned char res; // The result to return // State machine lookup on the register switch( uaddr ) { case UART_BUF: if( isSet(regs.lcr, UART_LCR_DLAB ) ) { // DLL byte res = (unsigned char)(regs.dl & 0x00ff); } else { res = regs.rbr; // Get the read data clr( regs.lsr, UART_LSR_DR ); // Clear the data ready bit clrIntr( UART_IER_RBFI ); } break; case UART_IER: if( isSet( regs.lcr, UART_LCR_DLAB ) ) { // DLH byte res = (unsigned char)((regs.dl & 0xff00) >> 8); } else { res = regs.ier; } break; case UART_IIR: res = regs.iir; clrIntr( UART_IER_TBEI ); break; case UART_LCR: res = regs.lcr; break; case UART_MCR: res = 0; break; // Write only case UART_LSR: res = regs.lsr; clr( regs.lsr, UART_LSR_BI ); clr( regs.lsr, UART_LSR_FE ); clr( regs.lsr, UART_LSR_PE ); clr( regs.lsr, UART_LSR_OE ); clrIntr( UART_IER_RLSI ); break; case UART_MSR: res = regs.msr; regs.msr = 0; clrIntr( UART_IER_MSI ); modemLoopback(); // May need resetting break; case UART_SCR: res = regs.scr; break; } return res; } // busRead() //! Process a write on the UART bus //! Switch on the address to determine behavior //! - UART_BUF //! - if UART_LSR_DLAB is set, write the low byte of the clock divisor and //! recalculate the character delay (UartSC::resetCharDelay()) //! - otherwise write the data to the transmit buffer, clear the buffer //! empty flags and notify the UartSC::busThread() using the //! UartSC::txReceived SystemC event. //! - UART_IER //! - if UART_LSR_DLAB is set, write the high byte of the clock divisor and //! recalculate the character delay (UartSC::resetCharDelay()) //! - otherwise set the instruction enable register //! - UART_IIR Ignored - read only //! - UART_LCR Set the line control register //! - UART_MCR Set the modem control regsiter //! - if loopback is set, set the MSR registers to correspond //! - UART_LSR Ignored - read only //! - UART_MSR Ignored - read only //! - UART_SCR Set the scratch register //! @param uaddr The address of the register being accessed //! @param wdata The value to be written void UartSC::busWrite( unsigned char uaddr, unsigned char wdata ) { // State machine lookup on the register switch( uaddr ) { case UART_BUF: if( isSet( regs.lcr, UART_LCR_DLAB ) ) { // DLL regs.dl = (regs.dl & 0xff00) | (unsigned short int)wdata; } else { regs.thr = wdata; clr( regs.lsr, UART_LSR_TEMT ); // Tx buffer now full clr( regs.lsr, UART_LSR_THRE ); clrIntr( UART_IER_TBEI ); txReceived.notify(); // Tell the bus thread } break; case UART_IER: if( isSet( regs.lcr, UART_LCR_DLAB ) ) { // DLH regs.dl = (regs.dl & 0x00ff) | ((unsigned short int)wdata << 8); } else { regs.ier = wdata; } break; case UART_IIR: break; // Read only case UART_LCR: regs.lcr = wdata; break; case UART_MCR: regs.mcr = wdata; modemLoopback(); break; case UART_LSR: break; // Read only case UART_MSR: break; // Read only case UART_SCR: regs.scr = wdata; break; } } // busWrite() //! Generate modem loopback signals //! Software relies on this to detect the UART type. Set the modem status bits //! as defined for modem loopback void UartSC::modemLoopback() { // Only if we are in loopback state if( isClr( regs.mcr, UART_MCR_LOOP )) { return; } // Delta status bits for what is about to change. if( (isSet( regs.mcr, UART_MCR_RTS ) && isClr( regs.msr, UART_MSR_CTS )) || (isClr( regs.mcr, UART_MCR_RTS ) && isSet( regs.msr, UART_MSR_CTS )) ) { set( regs.msr, UART_MSR_DCTS ); } else { clr( regs.msr, UART_MSR_DCTS ); } if( (isSet( regs.mcr, UART_MCR_DTR ) && isClr( regs.msr, UART_MSR_DSR )) || (isClr( regs.mcr, UART_MCR_DTR ) && isSet( regs.msr, UART_MSR_DSR )) ) { set( regs.msr, UART_MSR_DDSR ); } else { clr( regs.msr, UART_MSR_DDSR ); } if( (isSet( regs.mcr, UART_MCR_OUT1 ) && isClr( regs.msr, UART_MSR_RI )) || (isClr( regs.mcr, UART_MCR_OUT1 ) && isSet( regs.msr, UART_MSR_RI )) ) { set( regs.msr, UART_MSR_TERI ); } else { clr( regs.msr, UART_MSR_TERI ); } if( (isSet( regs.mcr, UART_MCR_OUT2 ) && isClr( regs.msr, UART_MSR_DCD )) || (isClr( regs.mcr, UART_MCR_OUT2 ) && isSet( regs.msr, UART_MSR_DCD )) ) { set( regs.msr, UART_MSR_DDCD ); } else { clr( regs.msr, UART_MSR_DDCD ); } // Loopback status bits if( isSet( regs.mcr, UART_MCR_RTS )) { // CTS = RTS set( regs.msr, UART_MSR_CTS ); } else { clr( regs.msr, UART_MSR_CTS ); } if( isSet( regs.mcr, UART_MCR_DTR )) { // DSR = DTR set( regs.msr, UART_MSR_DSR ); } else { clr( regs.msr, UART_MSR_DSR ); } if( isSet( regs.mcr, UART_MCR_OUT1 )) { // RI = OUT1 set( regs.msr, UART_MSR_RI ); } else { clr( regs.msr, UART_MSR_RI ); } if( isSet( regs.mcr, UART_MCR_OUT2 )) { // DSR = DTR set( regs.msr, UART_MSR_DCD ); } else { clr( regs.msr, UART_MSR_DCD ); } if( isSet( regs.msr, UART_MSR_DCTS ) | isSet( regs.msr, UART_MSR_DDSR ) | isSet( regs.msr, UART_MSR_TERI ) | isSet( regs.msr, UART_MSR_DDCD ) ) { genIntr( UART_IER_MSI ); } } // modemLoopback() //! Internal utility to set the IIR flags //! The IIR bits are set for the highest priority outstanding interrupt. void UartSC::setIntrFlags() { clr( regs.iir, UART_IIR_MASK ); // Clear current clr( regs.iir, UART_IIR_IPEND ); // 0 = pending if( isSet( intrPending, UART_IER_RLSI )) { // Priority order set( regs.iir, UART_IIR_RLS ); } else if( isSet( intrPending, UART_IER_RBFI )) { set( regs.iir, UART_IIR_RDA ); } else if( isSet( intrPending, UART_IER_TBEI )) { set( regs.iir, UART_IIR_THRE ); } else if( isSet( intrPending, UART_IER_MSI )) { set( regs.iir, UART_IIR_MOD ); } else { set( regs.iir, UART_IIR_IPEND ); // 1 = not pending } } // setIntrFlags() //! Generate an interrupt //! If the particular interrupt is enabled, set the relevant interrupt //! indicator flag, mark an interrupt as pending. //! @note There is no actual interrupt port in this class. The interrupt //! signal driving functionality will be added in a derived class //! @param ierFlag Indicator of which interrupt is to be cleared (as IER bit). void UartSC::genIntr( unsigned char ierFlag ) { if( isSet( regs.ier, ierFlag )) { set( intrPending, ierFlag ); // Mark this interrupt as pending. setIntrFlags(); // Show highest priority } } // genIntr() //! Clear an interrupt //! Clear the interrupts in priority order. //! If no interrupts remain asserted, clear the interrupt pending flag //! @note There is no actual interrupt port in this class. The interrupt //! signal driving functionality will be added in a derived class //! @param ierFlag Indicator of which interrupt is to be cleared (as IER bit). void UartSC::clrIntr( unsigned char ierFlag ) { clr( intrPending, ierFlag ); // Mark this interrupt as not pending setIntrFlags(); } // clrIntr() //! Set a bits in a register //! @param reg The register concerned //! @param flags The bits to set inline void UartSC::set( unsigned char ®, unsigned char flags ) { reg |= flags; } // set() //! Clear a bits in a register //! @param reg The register concerned //! @param flags The bits to set inline void UartSC::clr( unsigned char ®, unsigned char flags ) { reg &= ~flags; } // clr() //! Report if bits are set in a register //! @param reg The register concerned //! @param flags The bit to set //! @return True if the bit is set inline bool UartSC::isSet( unsigned char reg, unsigned char flags ) { return flags == (reg & flags); } // isSet() //! Report if bits are clear in a register //! @param reg The register concerned //! @param flags The bit to set //! @return True if the bit is clear inline bool UartSC::isClr( unsigned char reg, unsigned char flags ) { return flags != (reg & flags); } // isClr() // EOF _______________________________________________ http://www.opencores.org/mailman/listinfo/openrisc |
|
|
Re: Re: an1.pdf problem with step 7On Tue, 2009-02-24 at 10:59 +0000, Jeremy Bennett wrote:
> On Mon, 2009-02-23 at 14:29 +0000, Jeremy Bennett wrote: > > On Sun, 2009-02-22 at 23:49 +0000, Licínio Sousa wrote: > > > > > > I am trying to run step 7 of the AN1. > > > It happens that after linking i run the example, the terminal starts > > > but no echo appears in the terminal window. And no CHAR READ appear in > > > the LOG. > > > > > > > How strange. I've just checked and I have exactly the same result. I > > will investigate further. > There is now a new release of Or1ksim available, 0.3.0rc3 for download: http://www.opencores.org/pdownloads.cgi/list/or1k I've also updated the examples for the application note EAN1, to be consistent with this release of Or1ksim. http://www.embecosm.com/download/esp1.html Hope this all works well for you now. Let me know if you have any more problems. Best wishes, Jeremy -- Tel: +44 (1202) 416955 Cell: +44 (7970) 676050 SkypeID: jeremybennett Email: jeremy.bennett@... Web: www.embecosm.com _______________________________________________ http://www.opencores.org/mailman/listinfo/openrisc |
|
|
Re: Re: an1.pdf problem with step 7Hi Jeremy,
Thanks for your great assistance! I only tested the workaround so far ...and chars are recognized ...but they are not echoed in the xterm window. BR Licínio
On Tue, Feb 24, 2009 at 10:59 AM, Jeremy Bennett <jeremy.bennett@...> wrote:
_______________________________________________ http://www.opencores.org/mailman/listinfo/openrisc |
|
|
Re: Re: an1.pdf problem with step 7On Tue, 2009-02-24 at 18:00 +0000, Licínio Sousa wrote:
> Hi Jeremy, > Thanks for your great assistance! > > I only tested the workaround so far ...and chars are recognized ...but > they are not echoed in the xterm window. That's a bit disappointing. I did it in a bit of a rush, but I thought I'd got it right. Could you try with the new full releases, and see if you still have the same problem. BTW - what architecture are you using. I wonder if it is the same endianness as my Intel PC running Linux? Thanks, Jeremy -- Tel: +44 (1202) 416955 Cell: +44 (7970) 676050 SkypeID: jeremybennett Email: jeremy.bennett@... Web: www.embecosm.com _______________________________________________ http://www.opencores.org/mailman/listinfo/openrisc |
|
|
Re: Re: an1.pdf problem with step 7Hi,
I am also using intel PC ... a asus laptop running ubuntu. I will try the new release as soon as i fix a small problem on booting linux...it was working ok before..on 0.2.0 " io scheduler anticipatory registered (default) io scheduler deadline registered io scheduler cfq registered Serial: 8250/16550 driver $Revision: 1.90 $ 4 ports, IRQ sharing disabled serial8250.0: ttyS0 at MMIO 0x90000000 (irq = 2) is a 16550A console [ttyS0] enabled RAMDISK driver initialized: 16 RAM disks of 8192K size 1024 blocksize loop: module loaded TCP cubic registered NET: Registered protocol family 1 NET: Registered protocol family 17 NET: Registered protocol family 15 EXCEPTION: read out of memory (32-bit access to 4000002c) Runarunaround: Unhandled exception 0x200: EPC=0x4104 EXCEPTION: read out of memory (32-bit access to 4000032c) Runarunaround: Unhandled exception 0x200: EPC=0x4104 EXCEPTION: read out of memory (32-bit access to 4000032c) Runarunaround: Unhandled exception 0x200: EPC=0x4104 EXCEPTION: read out of memory (32-bit access to 4000032c) Runarunaround: Unhandled exception 0x200: EPC=0x4104 EXCEPTION: read out of memory (32-bit access to 4000032c) Runarunaround: Unhandled exception 0x200: EPC=0x4104 EXCEPTION: read out of memory (32-bit access to 4000032c) "
On Tue, Feb 24, 2009 at 7:58 PM, Jeremy Bennett <jeremy.bennett@...> wrote:
_______________________________________________ http://www.opencores.org/mailman/listinfo/openrisc |
|
|
Re: Re: an1.pdf problem with step 7On Tue, 2009-02-24 at 19:20 +0000, Licínio Sousa wrote:
> Hi, > I am also using intel PC ... a asus laptop running ubuntu. > > I will try the new release as soon as i fix a small problem on > booting linux...it was working ok before..on 0.2.0 > " > io scheduler anticipatory registered (default) > io scheduler deadline registered > io scheduler cfq registered > Serial: 8250/16550 driver $Revision: 1.90 $ 4 ports, IRQ sharing > disabled > serial8250.0: ttyS0 at MMIO 0x90000000 (irq = 2) is a 16550A > console [ttyS0] enabled > RAMDISK driver initialized: 16 RAM disks of 8192K size 1024 blocksize > loop: module loaded > TCP cubic registered > NET: Registered protocol family 1 > NET: Registered protocol family 17 > NET: Registered protocol family 15 > EXCEPTION: read out of memory (32-bit access to 4000002c) > > Runarunaround: Unhandled exception 0x200: EPC=0x4104 > EXCEPTION: read out of memory (32-bit access to 4000032c) > > Runarunaround: Unhandled exception 0x200: EPC=0x4104 > EXCEPTION: read out of memory (32-bit access to 4000032c) > > Runarunaround: Unhandled exception 0x200: EPC=0x4104 > EXCEPTION: read out of memory (32-bit access to 4000032c) > > Runarunaround: Unhandled exception 0x200: EPC=0x4104 > EXCEPTION: read out of memory (32-bit access to 4000032c) > > Runarunaround: Unhandled exception 0x200: EPC=0x4104 > EXCEPTION: read out of memory (32-bit access to 4000032c) " Hi Licínio, Which Linux kernel are you using? You do have the correct sim.cfg (the one in the Linux directory, not in the simulator directory)? I've just tried the 2.6.24 kernel and it worked OK for me. ATB, Jeremy -- Tel: +44 (1202) 416955 Cell: +44 (7970) 676050 SkypeID: jeremybennett Email: jeremy.bennett@... Web: www.embecosm.com _______________________________________________ http://www.opencores.org/mailman/listinfo/openrisc |
|
|
Re: Re: an1.pdf problem with step 72.6.23
i will check the sim.cfg When you say it works OK...you mean the echo in the xterm? or linux boot? br On Tue, Feb 24, 2009 at 8:40 PM, Jeremy Bennett <jeremy.bennett@...> wrote:
_______________________________________________ http://www.opencores.org/mailman/listinfo/openrisc |
|
|
Re: Re: an1.pdf problem with step 7Hi jeremy
The echo on xterm is ok with the new candidate! weeeee! Regarding the linux boot...i don´t understand. Runarunaround: Unhandled exception 0x200: EPC=0xc0009474 EXCEPTION: read out of memory (32-bit access to c0009474) Ii used the patch linux_2.6.24_or32_unified_simtested.bz2 - I am using 2.6.24 kernel - the sim.cfg is attached - I used the patch linux_2.6.24_or32_unified_simtested.bz2 But i am sure i had it working in my first experiment with 2.6.23....grrr Is there something missing...like ...configuring the chain as ROOT? BR L On Tue, Feb 24, 2009 at 7:54 PM, Licínio Sousa <licinios@...> wrote: 2.6.23 _______________________________________________ http://www.opencores.org/mailman/listinfo/openrisc |
|
|
Re: Re: an1.pdf problem with step 7On Wed, 2009-02-25 at 00:57 +0000, Licínio Sousa wrote:
> Hi jeremy > The echo on xterm is ok with the new candidate! weeeee! > > Regarding the linux boot...i don´t understand. > > > Runarunaround: Unhandled exception 0x200: EPC=0xc0009474 > EXCEPTION: read out of memory (32-bit access to c0009474) > > > Ii used the patch linux_2.6.24_or32_unified_simtested.bz2 > - I am using 2.6.24 kernel > - the sim.cfg is attached > - I used the patch linux_2.6.24_or32_unified_simtested.bz2 > > But i am sure i had it working in my first experiment with > 2.6.23....grrr > > > Is there something missing...like ...configuring the chain as ROOT? > BR Hi Licínio, It's a problem with Linux 2.6.24. This doesn't work with the standard GCC 3.4.4 compiler on the OpenCores website. You have to use Rich D'Addio's new GCC 4.2.2, which is available in the mof_orsoc directory on his FTP server www.meansoffreedom.com. Should be fine with 2.6.23. ATB, Jeremy -- Tel: +44 (1202) 416955 Cell: +44 (7970) 676050 SkypeID: jeremybennett Email: jeremy.bennett@... Web: www.embecosm.com _______________________________________________ http://www.opencores.org/mailman/listinfo/openrisc |
|
|
|
|
|
Re: Re: an1.pdf problem with step 7On Thu, 2009-02-26 at 01:59 +0100, licinios@... wrote:
> Hi Jeremy, > > - linux-2.6.23 is booting (I started everthing from scratch :) > > )...but it takes a lot of time ...around 5 mins..i think i already saw > > it booting faster than that in my first experiment...like 2 mins > > - Regarding step 10 > > I run ./IntrSocSC linux.cfg ../../linux-2.6.23/vmlinux but it doen't > > work! > > ELF sec = 50 > > Section: .text, vaddr: 0xc0000000, paddr: 0xf0000000 offset: > > 0x00002000, size: 0x0023d378 > > ERR: 8-bit program load out of memory area: f0000000 > > ERR: 8-bit program load out of memory area: f0000001 > It works for me. Looks like the problem is with linux.cfg, before the main IntrSocSC gets started. This is Or1ksim complaining that there is no memory declared at 0xf0000000 (where we try to load the ROM image). Yet that should be there in the linux.cfg that I ship with ESP1. I've attached my copy for you to compare. As you can see it includes the declaration: section memory pattern = 0x00 type = unknown name = "Flash" ce = 0 mc = 0 baseaddr = 0xf0000000 size = 0x01000000 delayr = 10 delayw = -1 end Hope this lets you track down the problem. You can speed up Linux boot considerably by turning off all the logging and statistics in the sim section. Again this suggests you have the wrong linux.cfg. Here's what I have in the distribution: section sim verbose = 0 debug = 0 profile = 0 history = 0 clkcycle = 10ns end ATB, Jeremy -- Tel: +44 (1202) 416955 Cell: +44 (7970) 676050 SkypeID: jeremybennett Email: jeremy.bennett@... Web: www.embecosm.com [linux.cfg] /* ---------------------------------------------------------------------------- * * linux.cfg -- Simulator configuration script file for Linux * * Copyright (C) 2001-2002, Marko Mlinar, markom@... * Copyright (C) 2008, Embecosm Limited <info@...> * 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. * * ---------------------------------------------------------------------------- * * This file is part of OpenRISC 1000 Architectural Simulator. It contains * the configuration suitable for running a Linux 2.6 kernel. * * For explanation of the different fields, see the default simulation * configuration file supplied with or1ksim (sim.cfg). * * The "generic" section is an extension to or1ksim to support modeling of * external peripherals. * * $Id$ * */ section memory pattern = 0x00 type = unknown name = "Flash" ce = 0 mc = 0 baseaddr = 0xf0000000 size = 0x01000000 delayr = 10 delayw = -1 end section memory pattern = 0x00 type = unknown name = "RAM" ce = 1 mc = 0 baseaddr = 0x00000000 size = 0x02000000 delayr = 20 delayw = 25 end section memory pattern = 0x00 type = unknown name = "SRAM" mc = 0 ce = 2 baseaddr = 0xa4000000 size = 0x00100000 delayr = 1 delayw = 2 end section immu enabled = 1 nsets = 64 nways = 1 pagesize = 8192 hitdelay = 0 missdelay = 0 end section dmmu enabled = 1 nsets = 64 nways = 1 pagesize = 8192 hitdelay = 0 missdelay = 0 end section sim verbose = 0 debug = 0 profile = 0 history = 0 clkcycle = 10ns end section cpu ver = 0x1200 rev = 0x0001 superscalar = 0 hazards = 0 dependstats = 0 sbuf_len = 0 end section tick enabled = 1 end section pic enabled = 1 edge_trigger = 1 end section generic enabled = 1 baseaddr = 0x90000000 size = 8 byte_enabled = 1 hw_enabled = 1 word_enabled = 1 name = "UART" end section mc enabled = 1 baseaddr = 0x93000000 POC = 0x00000008 index = 0 end /* Disabled Sections. The first two need all their additional fields due to a bug in Or1ksim */ section ic enabled = 0 nsets = 512 nways = 1 blocksize = 16 hitdelay = 20 missdelay = 20 end section dc enabled = 0 nsets = 512 nways = 1 blocksize = 16 load_hitdelay = 20 load_missdelay = 20 store_hitdelay = 20 store_missdelay = 20 end section VAPI enabled = 0 end section dma enabled = 0 end section pm enabled = 0 end section bpb enabled = 0 end section debug enabled = 0 end section uart enabled = 0 end section ethernet enabled = 0 end section gpio enabled = 0 end section ata enabled = 0 end section vga enabled = 0 end section fb enabled = 0 end section kbd enabled = 0 end _______________________________________________ http://www.opencores.org/mailman/listinfo/openrisc |
|
|
Re: Re: an1.pdf problem with step 7nop! i am using the same linux.cfg
I just did a xxdiff between the linux.cfg you sent me, the one in embecosm-esp1-sysc-tlm2.0-examples-1.1 and the one in embecosm-esp1-sysc-tlm2.0-examples-1.2 and they are the same....strange are you using orksim 0.3.0rc3 and linux-2.6.23? BR L On Thu, Feb 26, 2009 at 8:15 AM, Jeremy Bennett <jeremy.bennett@...> wrote: On Thu, 2009-02-26 at 01:59 +0100, licinios@... wrote: _______________________________________________ http://www.opencores.org/mailman/listinfo/openrisc |
|
|
Re: Re: an1.pdf problem with step 7Well! obviously...my mistake
the linux.cfg was in the upper directory...so it wasn't being loaded! Now it works STILL! Regarding the booting time. I doubled checked the sim.cfg and it still takes around 4 mins to boot ! I RUN or32-uclinux-sim -f sim.cfg vmlinuxRunning step 10 of AN1 ./IntrSocSC ../linux.cfg ../../linux-2.6.23/vmlinuxIt woks but it takes around 1 min to boot How fast is your linux boot in AN2? BR Licinio On Thu, Feb 26, 2009 at 12:15 PM, Licínio Sousa <licinios@...> wrote: nop! i am using the same linux.cfg _______________________________________________ http://www.opencores.org/mailman/listinfo/openrisc |
|
|
Re: Re: an1.pdf problem with step 7On Thu, 2009-02-26 at 14:51 +0000, Licínio Sousa wrote:
> Well! obviously...my mistake > the linux.cfg was in the upper directory...so it wasn't being loaded! > Now it works > > STILL! > > Regarding the booting time. I doubled checked the sim.cfg and it still > takes around 4 mins to boot ! > I RUN > or32-uclinux-sim -f sim.cfg vmlinux > Running step 10 of AN1 > ./IntrSocSC ../linux.cfg ../../linux-2.6.23/vmlinux > It woks but it takes around 1 min to boot > > How fast is your linux boot in AN2? Hi Licínio, My boot with the sim.cfg is slow. You'll see that the linux.cfg for EAN1 has turned off all the simulator logging (look at section sim). You can do the same with sim.cfg. I've suggested modifying sim.cfg to Rich D'Addio for future Linux distributions. ATB, Jeremy -- Tel: +44 (1202) 416955 Cell: +44 (7970) 676050 SkypeID: jeremybennett Email: jeremy.bennett@... Web: www.embecosm.com _______________________________________________ http://www.opencores.org/mailman/listinfo/openrisc |
|
|
Re: Re: an1.pdf problem with step 7Ok!
makes sense Thanks for your patient feedback :) Br L On Thu, Feb 26, 2009 at 3:51 PM, Jeremy Bennett <jeremy.bennett@...> wrote:
_______________________________________________ http://www.opencores.org/mailman/listinfo/openrisc |
|
|
Re: Re: an1.pdf problem with step 7Hi Jeremy,
On step 10 where is uart_loop_intr.c binary loaded ? Is it running over linux ? My understanding is that only the image ../linux-2.6.23/vmlinuxis loaded, but i see the uart loop program running ./IntrSocSC linux.cfg ../linux-2.6.23/vmlinux Thanks Licinio
On Thu, Feb 26, 2009 at 4:28 PM, Licínio Sousa <licinios@...> wrote: Ok! _______________________________________________ http://www.opencores.org/mailman/listinfo/openrisc |
|
|
|
| Free embeddable forum powered by Nabble | Forum Help |