00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "libraryitem.h"
00012 #include "logic.h"
00013 #include "ram.h"
00014 #include "variant.h"
00015
00016 #include <cmath>
00017 #include <klocale.h>
00018
00019 Item* RAM::construct( ItemDocument *itemDocument, bool newItem, const char *id )
00020 {
00021 return new RAM( (ICNDocument*)itemDocument, newItem, id );
00022 }
00023
00024 LibraryItem* RAM::libraryItem()
00025 {
00026 return new LibraryItem(
00027 QString("ec/ram"),
00028 i18n("RAM"),
00029 i18n("Integrated Circuits"),
00030 "ic2.png",
00031 LibraryItem::lit_component,
00032 RAM::construct
00033 );
00034 }
00035
00036 RAM::RAM( ICNDocument *icnDocument, bool newItem, const char *id )
00037 : Component( icnDocument, newItem, id ? id : "ram" )
00038 {
00039 m_name = i18n("RAM");
00040 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>.");
00041
00042 m_data = 0;
00043 m_pCS = 0;
00044 m_pOE = 0;
00045 m_pWE = 0;
00046 m_wordSize = 0;
00047 m_addressSize = 0;
00048
00049 createProperty( "wordSize", Variant::Type::Int );
00050 property("wordSize")->setCaption( i18n("Word Size") );
00051 property("wordSize")->setMinValue(1);
00052 property("wordSize")->setMaxValue(256);
00053 property("wordSize")->setValue(2);
00054
00055 createProperty( "addressSize", Variant::Type::Int );
00056 property("addressSize")->setCaption( i18n("Address Size") );
00057 property("addressSize")->setMinValue(1);
00058 property("addressSize")->setMaxValue(32);
00059 property("addressSize")->setValue(4);
00060
00061 m_data = createProperty( "data", Variant::Type::Raw )->value().asBitArray();
00062 }
00063
00064 RAM::~RAM()
00065 {
00066 }
00067
00068
00069 void RAM::dataChanged()
00070 {
00071 m_wordSize = dataInt("wordSize");
00072 m_addressSize = dataInt("addressSize");
00073
00074 int newSize = int( m_wordSize * std::pow( 2., m_addressSize ) );
00075 m_data.resize(newSize);
00076
00077 initPins();
00078 }
00079
00080
00081 void RAM::inStateChanged( bool newState )
00082 {
00083 Q_UNUSED(newState);
00084
00085 bool cs = m_pCS->isHigh();
00086 bool oe = m_pOE->isHigh();
00087 bool we = m_pWE->isHigh();
00088
00089 if ( !cs || !oe )
00090 {
00091 for ( int i = 0; i < m_wordSize; ++i )
00092 m_dataOut[i]->setHigh(false);
00093 }
00094
00095 if ( !cs || (!oe && !we) )
00096 return;
00097
00098 unsigned address = 0;
00099 for ( int i = 0; i < m_addressSize; ++i )
00100 address += (m_address[i]->isHigh() ? 1 : 0) << i;
00101
00102 if (we)
00103 {
00104 for ( int i = 0; i < m_wordSize; ++i )
00105 m_data[ m_wordSize * address + i ] = m_dataIn[i]->isHigh();
00106 }
00107
00108 if (oe)
00109 {
00110 for ( int i = 0; i < m_wordSize; ++i )
00111 m_dataOut[i]->setHigh( m_data[ m_wordSize * address + i ] );
00112 }
00113 }
00114
00115
00116 void RAM::initPins()
00117 {
00118 int oldWordSize = m_dataIn.size();
00119 int oldAddressSize = m_address.size();
00120
00121 int newWordSize = dataInt("wordSize");
00122 int newAddressSize = dataInt("addressSize");
00123
00124 if ( newAddressSize == oldAddressSize &&
00125 newWordSize == oldWordSize )
00126 return;
00127
00128 QStringList leftPins;
00129 leftPins << "CS" << "OE" << "WE";
00130 for ( int i = 0; i < newAddressSize; ++i )
00131 leftPins << QString("A%1").arg( QString::number(i) );
00132
00133 QStringList rightPins;
00134 for ( unsigned i = newWordSize; i > 0; --i )
00135 rightPins << QString("DI%1").arg( QString::number(i-1) );
00136 for ( unsigned i = newWordSize; i > 0; --i )
00137 rightPins << QString("DO%1").arg( QString::number(i-1) );
00138
00139
00140 for ( unsigned i = leftPins.size(); i < rightPins.size(); ++i )
00141 leftPins.append("");
00142 for ( unsigned i = rightPins.size(); i < leftPins.size(); ++i )
00143 rightPins.prepend("");
00144
00145 QStringList pins = leftPins + rightPins;
00146
00147 initDIPSymbol( pins, 72 );
00148 initDIP(pins);
00149
00150 ECNode *node;
00151
00152 if (!m_pCS)
00153 {
00154 node = ecNodeWithID("CS");
00155 m_pCS = createLogicIn(node);
00156 m_pCS->setCallback( this, (CallbackPtr)(&RAM::inStateChanged) );
00157 }
00158
00159 if (!m_pOE)
00160 {
00161 node = ecNodeWithID("OE");
00162 m_pOE = createLogicIn(node);
00163 m_pOE->setCallback( this, (CallbackPtr)(&RAM::inStateChanged) );
00164 }
00165
00166 if (!m_pWE)
00167 {
00168 node = ecNodeWithID("WE");
00169 m_pWE = createLogicIn(node);
00170 m_pWE->setCallback( this, (CallbackPtr)(&RAM::inStateChanged) );
00171 }
00172
00173 if ( newWordSize > oldWordSize )
00174 {
00175 m_dataIn.resize(newWordSize);
00176 m_dataOut.resize(newWordSize);
00177
00178 for ( int i = oldWordSize; i < newWordSize; ++i )
00179 {
00180 node = ecNodeWithID( QString("DI%1").arg( QString::number(i) ) );
00181 m_dataIn.insert( i, createLogicIn(node) );
00182 m_dataIn[i]->setCallback( this, (CallbackPtr)(&RAM::inStateChanged) );
00183
00184 node = ecNodeWithID( QString("DO%1").arg( QString::number(i) ) );
00185 m_dataOut.insert( i, createLogicOut(node, false) );
00186 }
00187 }
00188 else if ( newWordSize < oldWordSize )
00189 {
00190 for ( int i = newWordSize; i < oldWordSize; ++i )
00191 {
00192 QString id = QString("DO%1").arg( QString::number(i) );
00193 removeDisplayText(id);
00194 removeElement( m_dataIn[i], false );
00195 removeNode(id);
00196
00197 id = QString("DI%1").arg( QString::number(i) );
00198 removeDisplayText(id);
00199 removeElement( m_dataOut[i], false );
00200 removeNode(id);
00201 }
00202
00203 m_dataIn.resize(newWordSize);
00204 m_dataOut.resize(newWordSize);
00205 }
00206
00207 if ( newAddressSize > oldAddressSize )
00208 {
00209 m_address.resize(newAddressSize);
00210
00211 for ( int i = oldAddressSize; i < newAddressSize; ++i )
00212 {
00213 node = ecNodeWithID( QString("A%1").arg( QString::number(i) ) );
00214 m_address.insert( i, createLogicIn(node) );
00215 m_address[i]->setCallback( this, (CallbackPtr)(&RAM::inStateChanged) );
00216 }
00217 }
00218 else if ( newAddressSize < oldAddressSize )
00219 {
00220 for ( int i = newAddressSize; i < oldAddressSize; ++i )
00221 {
00222 QString id = QString("A%1").arg( QString::number(i) );
00223 removeDisplayText(id);
00224 removeElement( m_address[i], false );
00225 removeNode(id);
00226 }
00227
00228 m_address.resize(newAddressSize);
00229 }
00230 }
00231
00232