File indexing completed on 2024-05-05 05:46:09
0001 /*************************************************************************** 0002 * Copyright (C) 2005 by David Saxton * 0003 * david@bluehaze.org * 0004 * * 0005 * This program is free software; you can redistribute it and/or modify * 0006 * it under the terms of the GNU General Public License as published by * 0007 * the Free Software Foundation; either version 2 of the License, or * 0008 * (at your option) any later version. * 0009 ***************************************************************************/ 0010 0011 #include "ram.h" 0012 #include "libraryitem.h" 0013 #include "logic.h" 0014 #include "variant.h" 0015 0016 #include <KLocalizedString> 0017 #include <cmath> 0018 0019 void RAM_inStateChanged(void *objV, bool state) { 0020 RAM *objT = static_cast<RAM*>(objV); 0021 objT->inStateChanged(state); 0022 } 0023 0024 Item *RAM::construct(ItemDocument *itemDocument, bool newItem, const char *id) 0025 { 0026 return new RAM(static_cast<ICNDocument *>(itemDocument), newItem, id); 0027 } 0028 0029 LibraryItem *RAM::libraryItem() 0030 { 0031 return new LibraryItem(QStringList(QString("ec/ram")), i18n("RAM"), i18n("Integrated Circuits"), "ic2.png", LibraryItem::lit_component, RAM::construct); 0032 } 0033 0034 RAM::RAM(ICNDocument *icnDocument, bool newItem, const char *id) 0035 : Component(icnDocument, newItem, id ? id : "ram") 0036 { 0037 m_name = i18n("RAM"); 0038 0039 // m_data = nullptr; // should be initialized by the constructor anyway 0040 m_pCS = nullptr; 0041 m_pOE = nullptr; 0042 m_pWE = nullptr; 0043 m_wordSize = 0; 0044 m_addressSize = 0; 0045 0046 createProperty("wordSize", Variant::Type::Int); 0047 property("wordSize")->setCaption(i18n("Word Size")); 0048 property("wordSize")->setMinValue(1); 0049 property("wordSize")->setMaxValue(64); 0050 property("wordSize")->setValue(2); 0051 0052 createProperty("addressSize", Variant::Type::Int); 0053 property("addressSize")->setCaption(i18n("Address Size")); 0054 property("addressSize")->setMinValue(1); 0055 property("addressSize")->setMaxValue(24); 0056 property("addressSize")->setValue(4); 0057 0058 m_data = createProperty("data", Variant::Type::Raw)->value().toBitArray(); 0059 } 0060 0061 RAM::~RAM() 0062 { 0063 } 0064 0065 void RAM::dataChanged() 0066 { 0067 m_wordSize = dataInt("wordSize"); 0068 m_addressSize = dataInt("addressSize"); 0069 0070 int newSize = int(m_wordSize * std::pow(2., m_addressSize)); 0071 m_data.resize(newSize); 0072 0073 initPins(); 0074 } 0075 0076 void RAM::inStateChanged(bool newState) 0077 { 0078 Q_UNUSED(newState); 0079 0080 bool cs = m_pCS->isHigh(); 0081 bool oe = m_pOE->isHigh(); 0082 bool we = m_pWE->isHigh(); 0083 0084 if (!cs || !oe) { 0085 for (int i = 0; i < m_wordSize; ++i) 0086 m_dataOut[i]->setHigh(false); 0087 } 0088 0089 if (!cs || (!oe && !we)) 0090 return; 0091 0092 unsigned address = 0; 0093 for (int i = 0; i < m_addressSize; ++i) 0094 address += (m_address[i]->isHigh() ? 1 : 0) << i; 0095 0096 if (we) { 0097 for (int i = 0; i < m_wordSize; ++i) 0098 m_data[m_wordSize * address + i] = m_dataIn[i]->isHigh(); 0099 } 0100 0101 if (oe) { 0102 for (int i = 0; i < m_wordSize; ++i) 0103 m_dataOut[i]->setHigh(m_data[m_wordSize * address + i]); 0104 } 0105 } 0106 0107 void RAM::initPins() 0108 { 0109 int oldWordSize = m_dataIn.size(); 0110 int oldAddressSize = m_address.size(); 0111 0112 int newWordSize = dataInt("wordSize"); 0113 int newAddressSize = dataInt("addressSize"); 0114 0115 if (newAddressSize == oldAddressSize && newWordSize == oldWordSize) 0116 return; 0117 0118 QStringList leftPins; // Pins on left of IC 0119 leftPins << "CS" 0120 << "OE" 0121 << "WE"; 0122 for (int i = 0; i < newAddressSize; ++i) 0123 leftPins << QString("A%1").arg(QString::number(i)); 0124 0125 QStringList rightPins; // Pins on right of IC 0126 for (unsigned i = newWordSize; i > 0; --i) 0127 rightPins << QString("DI%1").arg(QString::number(i - 1)); 0128 for (unsigned i = newWordSize; i > 0; --i) 0129 rightPins << QString("DO%1").arg(QString::number(i - 1)); 0130 0131 // Make pin lists of consistent sizes 0132 for (int i = leftPins.size(); i < rightPins.size(); ++i) 0133 leftPins.append(""); 0134 for (int i = rightPins.size(); i < leftPins.size(); ++i) 0135 rightPins.prepend(""); 0136 0137 QStringList pins = leftPins + rightPins; 0138 0139 initDIPSymbol(pins, 72); 0140 initDIP(pins); 0141 0142 ECNode *node; 0143 0144 if (!m_pCS) { 0145 node = ecNodeWithID("CS"); 0146 m_pCS = createLogicIn(node); 0147 //m_pCS->setCallback(this, (CallbackPtr)(&RAM::inStateChanged)); 0148 m_pCS->setCallback2(RAM_inStateChanged, this); 0149 } 0150 0151 if (!m_pOE) { 0152 node = ecNodeWithID("OE"); 0153 m_pOE = createLogicIn(node); 0154 //m_pOE->setCallback(this, (CallbackPtr)(&RAM::inStateChanged)); 0155 m_pOE->setCallback2(RAM_inStateChanged, this); 0156 } 0157 0158 if (!m_pWE) { 0159 node = ecNodeWithID("WE"); 0160 m_pWE = createLogicIn(node); 0161 //m_pWE->setCallback(this, (CallbackPtr)(&RAM::inStateChanged)); 0162 m_pWE->setCallback2(RAM_inStateChanged, this); 0163 } 0164 0165 if (newWordSize > oldWordSize) { 0166 m_dataIn.resize(newWordSize); 0167 m_dataOut.resize(newWordSize); 0168 0169 for (int i = oldWordSize; i < newWordSize; ++i) { 0170 node = ecNodeWithID(QString("DI%1").arg(QString::number(i))); 0171 m_dataIn.insert(i, createLogicIn(node)); 0172 //m_dataIn[i]->setCallback(this, (CallbackPtr)(&RAM::inStateChanged)); 0173 m_dataIn[i]->setCallback2(RAM_inStateChanged, this); 0174 0175 node = ecNodeWithID(QString("DO%1").arg(QString::number(i))); 0176 m_dataOut.insert(i, createLogicOut(node, false)); 0177 } 0178 } else if (newWordSize < oldWordSize) { 0179 for (int i = newWordSize; i < oldWordSize; ++i) { 0180 QString id = QString("DO%1").arg(QString::number(i)); 0181 removeDisplayText(id); 0182 removeElement(m_dataIn[i], false); 0183 removeNode(id); 0184 0185 id = QString("DI%1").arg(QString::number(i)); 0186 removeDisplayText(id); 0187 removeElement(m_dataOut[i], false); 0188 removeNode(id); 0189 } 0190 0191 m_dataIn.resize(newWordSize); 0192 m_dataOut.resize(newWordSize); 0193 } 0194 0195 if (newAddressSize > oldAddressSize) { 0196 m_address.resize(newAddressSize); 0197 0198 for (int i = oldAddressSize; i < newAddressSize; ++i) { 0199 node = ecNodeWithID(QString("A%1").arg(QString::number(i))); 0200 m_address.insert(i, createLogicIn(node)); 0201 //m_address[i]->setCallback(this, (CallbackPtr)(&RAM::inStateChanged)); 0202 m_address[i]->setCallback2(RAM_inStateChanged, this); 0203 0204 } 0205 } else if (newAddressSize < oldAddressSize) { 0206 for (int i = newAddressSize; i < oldAddressSize; ++i) { 0207 QString id = QString("A%1").arg(QString::number(i)); 0208 removeDisplayText(id); 0209 removeElement(m_address[i], false); 0210 removeNode(id); 0211 } 0212 0213 m_address.resize(newAddressSize); 0214 } 0215 }