Logo Search packages:      
Sourcecode: ktechlab version File versions  Download package

ram.cpp

/***************************************************************************
 *   Copyright (C) 2005 by David Saxton                                    *
 *   david@bluehaze.org                                                    *
 *                                                                         *
 *   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.                                   *
 ***************************************************************************/

#include "libraryitem.h"
#include "logic.h"
#include "ram.h"
#include "variant.h"

#include <cmath>
#include <klocale.h>

Item* RAM::construct( ItemDocument *itemDocument, bool newItem, const char *id )
{
      return new RAM( (ICNDocument*)itemDocument, newItem, id );
}

LibraryItem* RAM::libraryItem()
{
      return new LibraryItem(
            QString("ec/ram"),
            i18n("RAM"),
            i18n("Integrated Circuits"),
            "ic2.png",
            LibraryItem::lit_component,
            RAM::construct
                  );
}

RAM::RAM( ICNDocument *icnDocument, bool newItem, const char *id )
      : Component( icnDocument, newItem, id ? id : "ram" )
{
      m_name = i18n("RAM");
      m_desc = i18n("This RAM stores data as a collection of words; each of which contains <i>word size</i> bits of data.<br><br>To read data, set the CS (<i>chip select</i>) and the OE (<i>output enable</i>) pins high, and select the word using the address pins <i>A*</i>. The word is outputted on the data-out pins: <i>DO*</i>.<br><br>To write data, set the CS (<i>chip select</i>) and the WE (<i>write enable</i>) pins high, and select the address to write to with the <i>A*</i> pins. Write to the selected word using the data-in pins: <i>DI*</i>.<br><br>The <i>Address Size</i> is the number of bits that determine an address; so the total number of words stored will be 2^<sup><i>Address Size</i></sup>.");
      
      m_data = 0l;
      m_pCS = 0l;
      m_pOE = 0l;
      m_pWE = 0l;
      m_wordSize = 0;
      m_addressSize = 0;
      
      createProperty( "wordSize", Variant::Type::Int );
      property("wordSize")->setCaption( i18n("Word Size") );
      property("wordSize")->setMinValue(1);
      property("wordSize")->setMaxValue(256);
      property("wordSize")->setValue(2);
      
      createProperty( "addressSize", Variant::Type::Int );
      property("addressSize")->setCaption( i18n("Address Size") );
      property("addressSize")->setMinValue(1);
      property("addressSize")->setMaxValue(32);
      property("addressSize")->setValue(4);
      
      m_data = createProperty( "data", Variant::Type::Raw )->value().asBitArray();
}

RAM::~RAM()
{
}


void RAM::dataChanged()
{
      m_wordSize = dataInt("wordSize");
      m_addressSize = dataInt("addressSize");
      
      int newSize = int( m_wordSize * std::pow( 2., m_addressSize ) );
      m_data.resize(newSize);
      
      initPins();
}


void RAM::inStateChanged( bool newState )
{
      Q_UNUSED(newState);
      
      bool cs = m_pCS->isHigh();
      bool oe = m_pOE->isHigh();
      bool we = m_pWE->isHigh();
      
      if ( !cs || !oe )
      {
            for ( int i = 0; i < m_wordSize; ++i )
                  m_dataOut[i]->setHigh(false);
      }
      
      if ( !cs || (!oe && !we) )
            return;
      
      unsigned address = 0;
      for ( int i = 0; i < m_addressSize; ++i )
            address += (m_address[i]->isHigh() ? 1 : 0) << i;
      
      if (we)
      {
            for ( int i = 0; i < m_wordSize; ++i )
                  m_data[ m_wordSize * address + i ] = m_dataIn[i]->isHigh();
      }
      
      if (oe)
      {
            for ( int i = 0; i < m_wordSize; ++i )
                  m_dataOut[i]->setHigh( m_data[ m_wordSize * address + i ] );
      }
}


void RAM::initPins()
{
      int oldWordSize = m_dataIn.size();
      int oldAddressSize = m_address.size();
      
      int newWordSize = dataInt("wordSize");
      int newAddressSize = dataInt("addressSize");
      
      if ( newAddressSize == oldAddressSize &&
                  newWordSize == oldWordSize )
            return;
      
      QStringList leftPins; // Pins on left of IC
      leftPins << "CS" << "OE" << "WE";
      for ( int i = 0; i < newAddressSize; ++i )
            leftPins << QString("A%1").arg( QString::number(i) );
      
      QStringList rightPins; // Pins on right of IC
      for ( unsigned i = newWordSize; i > 0; --i )
            rightPins << QString("DI%1").arg( QString::number(i-1) );
      for ( unsigned i = newWordSize; i > 0; --i )
            rightPins << QString("DO%1").arg( QString::number(i-1) );
      
      // Make pin lists of consistent sizes
      for ( unsigned i = leftPins.size(); i < rightPins.size(); ++i )
            leftPins.append("");
      for ( unsigned i = rightPins.size(); i < leftPins.size(); ++i )
            rightPins.prepend("");
      
      QStringList pins = leftPins + rightPins;
      
      initDIPSymbol( pins, 72 );
      initDIP(pins);
      
      ECNode *node;
      
      if (!m_pCS)
      {
            node =  ecNodeWithID("CS");
            m_pCS = createLogicIn(node);
            m_pCS->setCallback( this, (CallbackPtr)(&RAM::inStateChanged) );
      }
      
      if (!m_pOE)
      {
            node =  ecNodeWithID("OE");
            m_pOE = createLogicIn(node);
            m_pOE->setCallback( this, (CallbackPtr)(&RAM::inStateChanged) );
      }
      
      if (!m_pWE)
      {
            node =  ecNodeWithID("WE");
            m_pWE = createLogicIn(node);
            m_pWE->setCallback( this, (CallbackPtr)(&RAM::inStateChanged) );
      }
      
      if ( newWordSize > oldWordSize )
      {
            m_dataIn.resize(newWordSize);
            m_dataOut.resize(newWordSize);
            
            for ( int i = oldWordSize; i < newWordSize; ++i )
            {
                  node = ecNodeWithID( QString("DI%1").arg( QString::number(i) ) );
                  m_dataIn.insert( i, createLogicIn(node) );
                  m_dataIn[i]->setCallback( this, (CallbackPtr)(&RAM::inStateChanged) ); 
                  
                  node = ecNodeWithID( QString("DO%1").arg( QString::number(i) ) );
                  m_dataOut.insert( i, createLogicOut(node, false) );
            }
      }
      else if ( newWordSize < oldWordSize )
      {
            for ( int i = newWordSize; i < oldWordSize; ++i )
            {
                  QString id = QString("DO%1").arg( QString::number(i) );
                  removeDisplayText(id);
                  removeElement( m_dataIn[i], false );
                  removeNode(id);
                  
                  id = QString("DI%1").arg( QString::number(i) );
                  removeDisplayText(id);
                  removeElement( m_dataOut[i], false );
                  removeNode(id);
            }
            
            m_dataIn.resize(newWordSize);
            m_dataOut.resize(newWordSize);
      }
      
      if ( newAddressSize > oldAddressSize )
      {
            m_address.resize(newAddressSize);
            
            for ( int i = oldAddressSize; i < newAddressSize; ++i )
            {
                  node = ecNodeWithID( QString("A%1").arg( QString::number(i) ) );
                  m_address.insert( i, createLogicIn(node) );
                  m_address[i]->setCallback( this, (CallbackPtr)(&RAM::inStateChanged) );
            }
      }
      else if ( newAddressSize < oldAddressSize )
      {
            for ( int i = newAddressSize; i < oldAddressSize; ++i )
            {
                  QString id = QString("A%1").arg( QString::number(i) );
                  removeDisplayText(id);
                  removeElement( m_address[i], false );
                  removeNode(id);
            }
            
            m_address.resize(newAddressSize);
      }
}



Generated by  Doxygen 1.6.0   Back to index