Advertisement
Guest User

Untitled

a guest
Apr 5th, 2020
675
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 43.59 KB | None | 0 0
  1. /*******************************************************************************
  2. * Copyright (c) 2015-2017
  3. * School of Electrical, Computer and Energy Engineering, Arizona State University
  4. * PI: Prof. Shimeng Yu
  5. * All rights reserved.
  6. *  
  7. * This source code is part of NeuroSim - a device-circuit-algorithm framework to benchmark
  8. * neuro-inspired architectures with synaptic devices(e.g., SRAM and emerging non-volatile memory).
  9. * Copyright of the model is maintained by the developers, and the model is distributed under
  10. * the terms of the Creative Commons Attribution-NonCommercial 4.0 International Public License
  11. * http://creativecommons.org/licenses/by-nc/4.0/legalcode.
  12. * The source code is free and you can redistribute and/or modify it
  13. * by providing that the following conditions are met:
  14. *  
  15. *  1) Redistributions of source code must retain the above copyright notice,
  16. *     this list of conditions and the following disclaimer.
  17. *  
  18. *  2) Redistributions in binary form must reproduce the above copyright notice,
  19. *     this list of conditions and the following disclaimer in the documentation
  20. *     and/or other materials provided with the distribution.
  21. *  
  22. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  23. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  24. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  25. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  26. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  27. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  28. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  29. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  30. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  31. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  32. *
  33. * Developer list:
  34. *   Pai-Yu Chen     Email: pchen72 at asu dot edu
  35. *                    
  36. *   Xiaochen Peng   Email: xpeng15 at asu dot edu
  37. ********************************************************************************/
  38.  
  39. #include <ctime>
  40. #include <iostream>
  41. #include <math.h>
  42. #include "formula.h"
  43. #include "Array.h"
  44. #include "Param.h"
  45. #include "Cell.h"
  46.  
  47. extern Param *param;
  48.  
  49. /* General eNVM */
  50. void AnalogNVM::WriteEnergyCalculation(double wireCapCol) {
  51.     //printf("calculating write energy consumption\n");
  52.     if (nonlinearIV) {  // Currently only for cross-point array
  53.         /* I-V nonlinearity */
  54.         double conductancePrevAtVwLTP = NonlinearConductance(conductancePrev, NL, writeVoltageLTP, readVoltage, writeVoltageLTP);
  55.         double conductancePrevAtHalfVwLTP = NonlinearConductance(conductancePrev, NL, writeVoltageLTP, readVoltage, writeVoltageLTP/2);
  56.         double conductancePrevAtVwLTD = NonlinearConductance(conductancePrev, NL, writeVoltageLTD, readVoltage, writeVoltageLTD);
  57.         double conductancePrevAtHalfVwLTD = NonlinearConductance(conductancePrev, NL, writeVoltageLTD, readVoltage, writeVoltageLTD/2);
  58.         conductanceAtVwLTP = NonlinearConductance(conductance, NL, writeVoltageLTP, readVoltage, writeVoltageLTP);
  59.         conductanceAtHalfVwLTP = NonlinearConductance(conductance, NL, writeVoltageLTP, readVoltage, writeVoltageLTP/2);
  60.         conductanceAtVwLTD = NonlinearConductance(conductance, NL, writeVoltageLTD, readVoltage, writeVoltageLTD);
  61.         conductanceAtHalfVwLTD = NonlinearConductance(conductance, NL, writeVoltageLTD, readVoltage, writeVoltageLTD/2);
  62.         if (numPulse > 0) { // If the cell needs LTP pulses
  63.             writeEnergy = writeVoltageLTP * writeVoltageLTP * (conductancePrevAtVwLTP+conductanceAtVwLTP)/2 * writePulseWidthLTP * numPulse;
  64.             writeEnergy += writeVoltageLTP * writeVoltageLTP * wireCapCol * numPulse;
  65.             if (nonIdenticalPulse) {
  66.                 writeVoltageLTD = VinitLTD + (VinitLTD + VstepLTD * maxNumLevelLTD);
  67.             }
  68.             writeEnergy += writeVoltageLTD/2 * writeVoltageLTD/2 * conductanceAtHalfVwLTD * writeLatencyLTD;    // Half-selected during LTD phase (use the new conductance value if LTP phase is before LTD phase)
  69.             writeEnergy += writeVoltageLTD/2 * writeVoltageLTD/2 * wireCapCol;
  70.         } else if (numPulse < 0) {  // If the cell needs LTD pulses
  71.             if (nonIdenticalPulse) {
  72.                 writeVoltageLTP = VinitLTP + (VinitLTP + VstepLTP * maxNumLevelLTP);
  73.             }
  74.             writeEnergy = writeVoltageLTP/2 * writeVoltageLTP/2 * conductancePrevAtHalfVwLTP * writeLatencyLTP;    // Half-selected during LTP phase (use the old conductance value if LTP phase is before LTD phase)
  75.             writeEnergy += writeVoltageLTP/2 * writeVoltageLTP/2 * wireCapCol;
  76.             writeEnergy += writeVoltageLTD * writeVoltageLTD * wireCapCol * (-numPulse);
  77.             writeEnergy += writeVoltageLTD * writeVoltageLTD * (conductancePrevAtVwLTD+conductanceAtVwLTD)/2 * writePulseWidthLTD * (-numPulse);
  78.         } else {    // Half-selected during both LTP and LTD phases
  79.             if (nonIdenticalPulse) {
  80.                 writeVoltageLTP = VinitLTP + (VinitLTP + VstepLTP * maxNumLevelLTP);
  81.                 writeVoltageLTD = VinitLTD + (VinitLTD + VstepLTD * maxNumLevelLTD);
  82.             }
  83.             writeEnergy = writeVoltageLTP/2 * writeVoltageLTP/2 * conductancePrevAtHalfVwLTP * writeLatencyLTP;
  84.             writeEnergy += writeVoltageLTP/2 * writeVoltageLTP/2 * wireCapCol;
  85.             writeEnergy += writeVoltageLTD/2 * writeVoltageLTD/2 * conductancePrevAtHalfVwLTD * writeLatencyLTD;
  86.             writeEnergy += writeVoltageLTD/2 * writeVoltageLTD/2 * wireCapCol;
  87.         }
  88.     } else {    // If not cross-point array or not considering I-V nonlinearity
  89.         if (FeFET) {    // FeFET structure
  90.             if (cmosAccess) {
  91.                 if (numPulse > 0) { // If the cell needs LTP pulses
  92.                     writeEnergy = writeVoltageLTP * writeVoltageLTP * (gateCapFeFET + wireCapCol) * numPulse;
  93.                     if (nonIdenticalPulse) {
  94.                         writeVoltageLTD = VinitLTD + VstepLTD * maxNumLevelLTD;
  95.                     }
  96.                     writeEnergy += writeVoltageLTD * writeVoltageLTD * (gateCapFeFET + wireCapCol);
  97.                 } else if (numPulse < 0) {  // If the cell needs LTD pulses
  98.                     writeEnergy = writeVoltageLTD * writeVoltageLTD * (gateCapFeFET + wireCapCol) * (-numPulse);
  99.                 } else {    // Half-selected during both LTP and LTD phases
  100.                     if (nonIdenticalPulse) {
  101.                         writeVoltageLTD = VinitLTD + VstepLTD * maxNumLevelLTD;
  102.                     }
  103.                     writeEnergy = writeVoltageLTD * writeVoltageLTD * (gateCapFeFET + wireCapCol);
  104.                 }
  105.             } else {
  106.                 puts("FeFET structure is not compatible with crossbar");
  107.                 exit(-1);
  108.             }
  109.         } else {
  110.             if (numPulse > 0) { // If the cell needs LTP pulses
  111.                 writeEnergy = writeVoltageLTP * writeVoltageLTP * (conductancePrev+conductance)/2 * writePulseWidthLTP * numPulse;
  112.                 writeEnergy += writeVoltageLTP * writeVoltageLTP * wireCapCol * numPulse;
  113.                 if (!cmosAccess) {  // Crossbar
  114.                     if (nonIdenticalPulse) {
  115.                         writeVoltageLTD = VinitLTD + (VinitLTD + VstepLTD * maxNumLevelLTD);
  116.                     }
  117.                     writeEnergy += writeVoltageLTD/2 * writeVoltageLTD/2 * conductance * writeLatencyLTD;    // Half-selected during LTD phase (use the new conductance value if LTP phase is before LTD phase)
  118.                     writeEnergy += writeVoltageLTD/2 * writeVoltageLTD/2 * wireCapCol;
  119.                 }
  120.             } else if (numPulse < 0) {  // If the cell needs LTD pulses
  121.                 if (!cmosAccess) {  // Crossbar
  122.                     if (nonIdenticalPulse) {
  123.                         writeVoltageLTP = VinitLTP + (VinitLTP + VstepLTP * maxNumLevelLTP);
  124.                     }
  125.                     writeEnergy = writeVoltageLTP/2 * writeVoltageLTP/2 * conductancePrev * writeLatencyLTP;    // Half-selected during LTP phase (use the old conductance value if LTP phase is before LTD phase)
  126.                     writeEnergy += writeVoltageLTP/2 * writeVoltageLTP/2 * wireCapCol;
  127.                 } else {    // 1T1R
  128.                     if (nonIdenticalPulse) {
  129.                         writeVoltageLTP = VinitLTP + VstepLTP * maxNumLevelLTP;
  130.                     }
  131.                     writeEnergy = writeVoltageLTP * writeVoltageLTP * wireCapCol;
  132.                 }
  133.                 writeEnergy += writeVoltageLTD * writeVoltageLTD * wireCapCol * (-numPulse);
  134.                 writeEnergy += writeVoltageLTD * writeVoltageLTD * (conductancePrev+conductance)/2 * writePulseWidthLTD * (-numPulse);
  135.             } else {    // Half-selected during both LTP and LTD phases
  136.                 if (!cmosAccess) {  // Crossbar
  137.                     if (nonIdenticalPulse) {
  138.                         writeVoltageLTP = VinitLTP + (VinitLTP + VstepLTP * maxNumLevelLTP);
  139.                         writeVoltageLTD = VinitLTD + (VinitLTD + VstepLTD * maxNumLevelLTD);
  140.                     }
  141.                     writeEnergy = writeVoltageLTP/2 * writeVoltageLTP/2 * conductancePrev * writeLatencyLTP;
  142.                     writeEnergy += writeVoltageLTP/2 * writeVoltageLTP/2 * wireCapCol;
  143.                     writeEnergy += writeVoltageLTD/2 * writeVoltageLTD/2 * conductancePrev * writeLatencyLTD;
  144.                     writeEnergy += writeVoltageLTD/2 * writeVoltageLTD/2 * wireCapCol;
  145.                 } else {    // 1T1R
  146.                     if (nonIdenticalPulse) {
  147.                         writeVoltageLTP = VinitLTP + VstepLTP * maxNumLevelLTP;
  148.                     }
  149.                     writeEnergy = writeVoltageLTP * writeVoltageLTP * wireCapCol;
  150.                 }
  151.             }
  152.         }
  153.     }
  154.     //printf("writeEnergy is %.4e\n", writeEnergy);
  155. }
  156.  
  157. /* Ideal device (no weight update nonlinearity) */
  158. IdealDevice::IdealDevice(int x, int y) {
  159.     this->x = x; this->y = y;   // Cell location: x (column) and y (row) start from index 0
  160.     maxConductance = 5e-6;      // Maximum cell conductance (S)
  161.     minConductance = 100e-9;        // Minimum cell conductance (S)
  162.     avgMaxConductance = maxConductance; // Average maximum cell conductance (S)
  163.     avgMinConductance = minConductance; // Average minimum cell conductance (S)
  164.     conductance = minConductance;   // Current conductance (S) (dynamic variable)
  165.     conductancePrev = conductance;  // Previous conductance (S) (dynamic variable)
  166.     readVoltage = 0.5;  // On-chip read voltage (Vr) (V)
  167.     readPulseWidth = 5e-9;  // Read pulse width (s) (will be determined by ADC)
  168.     writeVoltageLTP = 2;    // Write voltage (V) for LTP or weight increase
  169.     writeVoltageLTD = 2;    // Write voltage (V) for LTD or weight decrease
  170.     writePulseWidthLTP = 10e-9; // Write pulse width (s) for LTP or weight increase
  171.     writePulseWidthLTD = 10e-9; // Write pulse width (s) for LTD or weight decrease
  172.     writeEnergy = 0;    // Dynamic variable for calculation of write energy (J)
  173.     maxNumLevelLTP = 500;   // Maximum number of conductance states during LTP or weight increase
  174.     maxNumLevelLTD = 500;   // Maximum number of conductance states during LTD or weight decrease
  175.     numPulse = 0;   // Number of write pulses used in the most recent write operation (dynamic variable)
  176.     cmosAccess = true;  // True: Pseudo-crossbar (1T1R), false: cross-point
  177.     FeFET = false;      // True: FeFET structure (Pseudo-crossbar only, should be cmosAccess=1)
  178.     gateCapFeFET = 2.1717e-18;  // Gate capacitance of FeFET (F)
  179.     resistanceAccess = 15e3;    // The resistance of transistor (Ohm) in Pseudo-crossbar array when turned ON
  180.     nonlinearIV = false;    // Consider I-V nonlinearity or not (Currently for cross-point array only)
  181.     nonIdenticalPulse = false;  // Use non-identical pulse scheme in weight update or not (should be false here)
  182.                                 // Don't care other non-identical pulse parameters
  183.     NL = 10;    // Nonlinearity in write scheme (the current ratio between Vw and Vw/2), assuming for the LTP side
  184.     if (nonlinearIV) {  // Currently for cross-point array only
  185.         double Vr_exp = readVoltage;  // XXX: Modify this value to Vr in the reported measurement data (can be different than readVoltage)
  186.         // Calculation of conductance at on-chip Vr
  187.         maxConductance = NonlinearConductance(maxConductance, NL, writeVoltageLTP, Vr_exp, readVoltage);
  188.         minConductance = NonlinearConductance(minConductance, NL, writeVoltageLTP, Vr_exp, readVoltage);
  189.     }
  190.     readNoise = false;  // Consider read noise or not
  191.     sigmaReadNoise = 0.25;  // Sigma of read noise in gaussian distribution
  192.     gaussian_dist = new std::normal_distribution<double>(0, sigmaReadNoise);    // Set up mean and stddev for read noise
  193.    
  194.     /* Conductance range variation */  
  195.     conductanceRangeVar = false;    // Consider variation of conductance range or not
  196.     maxConductanceVar = 0;  // Sigma of maxConductance variation (S)
  197.     minConductanceVar = 0;  // Sigma of minConductance variation (S)
  198.     std::mt19937 localGen;
  199.     localGen.seed(std::time(0));
  200.     gaussian_dist_maxConductance = new std::normal_distribution<double>(0, maxConductanceVar);
  201.     gaussian_dist_minConductance = new std::normal_distribution<double>(0, minConductanceVar);
  202.     if (conductanceRangeVar) {
  203.         maxConductance += (*gaussian_dist_maxConductance)(localGen);
  204.         minConductance += (*gaussian_dist_minConductance)(localGen);
  205.         if (minConductance >= maxConductance || maxConductance < 0 || minConductance < 0 ) {    // Conductance variation check
  206.             puts("[Error] Conductance variation check not passed. The variation may be too large.");
  207.             exit(-1);
  208.         }
  209.         // Use the code below instead for re-choosing the variation if the check is not passed
  210.         //do {
  211.         //  maxConductance = avgMaxConductance + (*gaussian_dist_maxConductance)(localGen);
  212.         //  minConductance = avgMinConductance + (*gaussian_dist_minConductance)(localGen);
  213.         //} while (minConductance >= maxConductance || maxConductance < 0 || minConductance < 0);
  214.     }
  215.    
  216.     heightInFeatureSize = cmosAccess? 4 : 2;    // Cell height = 4F (Pseudo-crossbar) or 2F (cross-point)
  217.     widthInFeatureSize = cmosAccess? (FeFET? 6 : 4) : 2;    // Cell width = 6F (FeFET) or 4F (Pseudo-crossbar) or 2F (cross-point)
  218. }
  219.  
  220. double IdealDevice::Read(double voltage) {
  221.     extern std::mt19937 gen;
  222.     // TODO: nonlinear read
  223.     if (readNoise) {
  224.         return voltage * conductance * (1 + (*gaussian_dist)(gen));
  225.     } else {
  226.         return voltage * conductance;
  227.     }
  228. }
  229.  
  230. void IdealDevice::Write(double deltaWeightNormalized, double weight, double minWeight, double maxWeight) {
  231.     extern std::mt19937 gen;
  232.     if (deltaWeightNormalized >= 0) {
  233.         deltaWeightNormalized = deltaWeightNormalized/(maxWeight-minWeight);
  234.         deltaWeightNormalized = truncate(deltaWeightNormalized, maxNumLevelLTP);
  235.         numPulse = deltaWeightNormalized * maxNumLevelLTP;
  236.     } else {
  237.         deltaWeightNormalized = deltaWeightNormalized/(maxWeight-minWeight);
  238.         deltaWeightNormalized = truncate(deltaWeightNormalized, maxNumLevelLTD);
  239.         numPulse = deltaWeightNormalized * maxNumLevelLTD;                            // will be a negative number
  240.     }
  241.     double conductanceNew = conductance + deltaWeightNormalized * (maxConductance - minConductance);
  242.     if (conductanceNew > maxConductance) {
  243.         conductanceNew = maxConductance;
  244.     } else if (conductanceNew < minConductance) {
  245.         conductanceNew = minConductance;
  246.     }
  247.  
  248.     /* Write latency calculation */
  249.     if (numPulse > 0) { // LTP
  250.         writeLatencyLTP = numPulse * writePulseWidthLTP;
  251.         writeLatencyLTD = 0;
  252.     } else {    // LTD
  253.         writeLatencyLTP = 0;
  254.         writeLatencyLTD = -numPulse * writePulseWidthLTD;
  255.     }
  256.    
  257.     conductancePrev = conductance;
  258.     conductance = conductanceNew;
  259. }
  260.  
  261. /* Real Device */
  262. RealDevice::RealDevice(int x, int y) {
  263.     this->x = x; this->y = y;   // Cell location: x (column) and y (row) start from index 0
  264.     maxConductance = 3.8462e-8;     // Maximum cell conductance (S)
  265.     minConductance = 3.0769e-9; // Minimum cell conductance (S)
  266.     avgMaxConductance = maxConductance; // Average maximum cell conductance (S)
  267.     avgMinConductance = minConductance; // Average minimum cell conductance (S)
  268.     conductance = minConductance;   // Current conductance (S) (dynamic variable)
  269.     conductancePrev = conductance;  // Previous conductance (S) (dynamic variable)
  270.     readVoltage = 0.5;  // On-chip read voltage (Vr) (V)
  271.     readPulseWidth = 5e-9;  // Read pulse width (s) (will be determined by ADC)
  272.     writeVoltageLTP = 3.2;  // Write voltage (V) for LTP or weight increase
  273.     writeVoltageLTD = 2.8;  // Write voltage (V) for LTD or weight decrease
  274.     writePulseWidthLTP = 300e-6;    // Write pulse width (s) for LTP or weight increase
  275.     writePulseWidthLTD = 300e-6;    // Write pulse width (s) for LTD or weight decrease
  276.     writeEnergy = 0;    // Dynamic variable for calculation of write energy (J)
  277.     maxNumLevelLTP = 800;   // Maximum number of conductance states during LTP or weight increase
  278.     maxNumLevelLTD = 800;   // Maximum number of conductance states during LTD or weight decrease
  279.     numPulse = 0;   // Number of write pulses used in the most recent write operation (dynamic variable)
  280.     cmosAccess = true;  // True: Pseudo-crossbar (1T1R), false: cross-point
  281.     FeFET = false;      // True: FeFET structure (Pseudo-crossbar only, should be cmosAccess=1)
  282.     gateCapFeFET = 2.1717e-18;  // Gate capacitance of FeFET (F)
  283.     resistanceAccess = 15e3;    // The resistance of transistor (Ohm) in Pseudo-crossbar array when turned ON
  284.     nonlinearIV = false;    // Consider I-V nonlinearity or not (Currently for cross-point array only)
  285.     NL = 10;    // I-V nonlinearity in write scheme (the current ratio between Vw and Vw/2), assuming for the LTP side
  286.     if (nonlinearIV) {  // Currently for cross-point array only
  287.         double Vr_exp = readVoltage;  // XXX: Modify this value to Vr in the reported measurement data (can be different than readVoltage)
  288.         // Calculation of conductance at on-chip Vr
  289.         maxConductance = NonlinearConductance(maxConductance, NL, writeVoltageLTP, Vr_exp, readVoltage);
  290.         minConductance = NonlinearConductance(minConductance, NL, writeVoltageLTP, Vr_exp, readVoltage);
  291.     }
  292.     nonlinearWrite = true;  // Consider weight update nonlinearity or not
  293.     nonIdenticalPulse = false;  // Use non-identical pulse scheme in weight update or not
  294.     if (nonIdenticalPulse) {
  295.         VinitLTP = 2.85;    // Initial write voltage for LTP or weight increase (V)
  296.         VstepLTP = 0.05;    // Write voltage step for LTP or weight increase (V)
  297.         VinitLTD = 2.1;     // Initial write voltage for LTD or weight decrease (V)
  298.         VstepLTD = 0.05;    // Write voltage step for LTD or weight decrease (V)
  299.         PWinitLTP = 75e-9;  // Initial write pulse width for LTP or weight increase (s)
  300.         PWstepLTP = 5e-9;   // Write pulse width for LTP or weight increase (s)
  301.         PWinitLTD = 75e-9;  // Initial write pulse width for LTD or weight decrease (s)
  302.         PWstepLTD = 5e-9;   // Write pulse width for LTD or weight decrease (s)
  303.         writeVoltageSquareSum = 0;  // Sum of V^2 of non-identical pulses (dynamic variable)
  304.     }
  305.     readNoise = false;      // Consider read noise or not
  306.     sigmaReadNoise = 0;     // Sigma of read noise in gaussian distribution
  307.     gaussian_dist = new std::normal_distribution<double>(0, sigmaReadNoise);    // Set up mean and stddev for read noise
  308.  
  309.     std::mt19937 localGen;  // It's OK not to use the external gen, since here the device-to-device vairation is a one-time deal
  310.     localGen.seed(std::time(0));
  311.    
  312.     /* Device-to-device weight update variation */
  313.     NL_LTP = 2.4;   // LTP nonlinearity
  314.     NL_LTD = -4.88; // LTD nonlinearity
  315.     sigmaDtoD = 0;  // Sigma of device-to-device weight update vairation in gaussian distribution
  316.     gaussian_dist2 = new std::normal_distribution<double>(0, sigmaDtoD);    // Set up mean and stddev for device-to-device weight update vairation
  317.     paramALTP = getParamA(NL_LTP + (*gaussian_dist2)(localGen)) * maxNumLevelLTP;   // Parameter A for LTP nonlinearity
  318.     paramALTD = getParamA(NL_LTD + (*gaussian_dist2)(localGen)) * maxNumLevelLTD;   // Parameter A for LTD nonlinearity
  319.  
  320.     /* Cycle-to-cycle weight update variation */
  321.     sigmaCtoC = 0.035* (maxConductance - minConductance);   // Sigma of cycle-to-cycle weight update vairation: defined as the percentage of conductance range
  322.     gaussian_dist3 = new std::normal_distribution<double>(0, sigmaCtoC);    // Set up mean and stddev for cycle-to-cycle weight update vairation
  323.  
  324.     /* Conductance range variation */
  325.     conductanceRangeVar = false;    // Consider variation of conductance range or not
  326.     maxConductanceVar = 0;  // Sigma of maxConductance variation (S)
  327.     minConductanceVar = 0;  // Sigma of minConductance variation (S)
  328.     gaussian_dist_maxConductance = new std::normal_distribution<double>(0, maxConductanceVar);
  329.     gaussian_dist_minConductance = new std::normal_distribution<double>(0, minConductanceVar);
  330.     if (conductanceRangeVar) {
  331.         maxConductance += (*gaussian_dist_maxConductance)(localGen);
  332.         minConductance += (*gaussian_dist_minConductance)(localGen);
  333.         if (minConductance >= maxConductance || maxConductance < 0 || minConductance < 0 ) {    // Conductance variation check
  334.             puts("[Error] Conductance variation check not passed. The variation may be too large.");
  335.             exit(-1);
  336.         }
  337.         // Use the code below instead for re-choosing the variation if the check is not passed
  338.         //do {
  339.         //  maxConductance = avgMaxConductance + (*gaussian_dist_maxConductance)(localGen);
  340.         //  minConductance = avgMinConductance + (*gaussian_dist_minConductance)(localGen);
  341.         //} while (minConductance >= maxConductance || maxConductance < 0 || minConductance < 0);
  342.     }
  343.  
  344.         heightInFeatureSize = cmosAccess? 4 : 2; // Cell height = 4F (Pseudo-crossbar) or 2F (cross-point)
  345.         widthInFeatureSize = cmosAccess? (FeFET? 6 : 4) : 2; //// Cell width = 6F (FeFET) or 4F (Pseudo-crossbar) or 2F (cross-point)
  346. }
  347.  
  348. double RealDevice::Read(double voltage) {   // Return read current (A)
  349.     extern std::mt19937 gen;
  350.     if (nonlinearIV) {
  351.         // TODO: nonlinear read
  352.         if (readNoise) {
  353.             return voltage * conductance * (1 + (*gaussian_dist)(gen));
  354.         } else {
  355.             return voltage * conductance;
  356.         }
  357.     } else {
  358.         if (readNoise) {
  359.             return voltage * conductance * (1 + (*gaussian_dist)(gen));
  360.         } else {
  361.             return voltage * conductance;
  362.         }
  363.     }
  364. }
  365.  
  366. void RealDevice::Write(double deltaWeightNormalized, double weight, double minWeight, double maxWeight) {
  367.     double conductanceNew = conductance;    // =conductance if no update
  368.     if (deltaWeightNormalized > 0) {    // LTP
  369.         deltaWeightNormalized = deltaWeightNormalized/(maxWeight-minWeight);
  370.         deltaWeightNormalized = truncate(deltaWeightNormalized, maxNumLevelLTP);
  371.         numPulse = deltaWeightNormalized * maxNumLevelLTP;
  372.         if (nonlinearWrite) {
  373.             paramBLTP = (maxConductance - minConductance) / (1 - exp(-maxNumLevelLTP/paramALTP));
  374.             xPulse = InvNonlinearWeight(conductance, maxNumLevelLTP, paramALTP, paramBLTP, minConductance);
  375.             conductanceNew = NonlinearWeight(xPulse+numPulse, maxNumLevelLTP, paramALTP, paramBLTP, minConductance);
  376.         } else {
  377.             xPulse = (conductance - minConductance) / (maxConductance - minConductance) * maxNumLevelLTP;
  378.             conductanceNew = (xPulse+numPulse) / maxNumLevelLTP * (maxConductance - minConductance) + minConductance;
  379.         }
  380.     } else {    // LTD
  381.         deltaWeightNormalized = deltaWeightNormalized/(maxWeight-minWeight);
  382.         deltaWeightNormalized = truncate(deltaWeightNormalized, maxNumLevelLTD);
  383.         numPulse = deltaWeightNormalized * maxNumLevelLTD;
  384.         if (nonlinearWrite) {
  385.             paramBLTD = (maxConductance - minConductance) / (1 - exp(-maxNumLevelLTD/paramALTD));
  386.             xPulse = InvNonlinearWeight(conductance, maxNumLevelLTD, paramALTD, paramBLTD, minConductance);
  387.             conductanceNew = NonlinearWeight(xPulse+numPulse, maxNumLevelLTD, paramALTD, paramBLTD, minConductance);
  388.         } else {
  389.             xPulse = (conductance - minConductance) / (maxConductance - minConductance) * maxNumLevelLTD;
  390.             conductanceNew = (xPulse+numPulse) / maxNumLevelLTD * (maxConductance - minConductance) + minConductance;
  391.         }
  392.     }
  393.  
  394.     // if(param->isFirst) {
  395.     //  param->deltaTemp = deltaWeightNormalized;
  396.     //  param->conductanceTemp = conductanceNew;
  397.     //  param->numPulseTemp = numPulse;
  398.     //  param->xPulseTemp = xPulse;
  399.     // }
  400.  
  401.     /* Cycle-to-cycle variation */
  402.     extern std::mt19937 gen;
  403.     if (sigmaCtoC && numPulse != 0) {
  404.         conductanceNew += (*gaussian_dist3)(gen) * sqrt(abs(numPulse)); // Absolute variation
  405.     }
  406.    
  407.     if (conductanceNew > maxConductance) {
  408.         conductanceNew = maxConductance;
  409.     } else if (conductanceNew < minConductance) {
  410.         conductanceNew = minConductance;
  411.     }
  412.  
  413.     // if(param->isFirst)
  414.     //  param->conductanceMINMAXTemp = conductanceNew;
  415.  
  416.     /* Write latency calculation */
  417.     if (!nonIdenticalPulse) {   // Identical write pulse scheme
  418.         if (numPulse > 0) { // LTP
  419.             writeLatencyLTP = numPulse * writePulseWidthLTP;
  420.             writeLatencyLTD = 0;
  421.         } else {    // LTD
  422.             writeLatencyLTP = 0;
  423.             writeLatencyLTD = -numPulse * writePulseWidthLTD;
  424.         }
  425.     } else {    // Non-identical write pulse scheme
  426.         writeLatencyLTP = 0;
  427.         writeLatencyLTD = 0;
  428.         writeVoltageSquareSum = 0;
  429.         double V = 0;
  430.         double PW = 0;
  431.         if (numPulse > 0) { // LTP
  432.             for (int i=0; i<numPulse; i++) {
  433.                 V = VinitLTP + (xPulse+i) * VstepLTP;
  434.                 PW = PWinitLTP + (xPulse+i) * PWstepLTP;
  435.                 writeLatencyLTP += PW;
  436.                 writeVoltageSquareSum += V * V;
  437.             }
  438.             writePulseWidthLTP = writeLatencyLTP / numPulse;
  439.         } else {    // LTD
  440.             for (int i=0; i<(-numPulse); i++) {
  441.                 V = VinitLTD + (maxNumLevelLTD-xPulse+i) * VstepLTD;
  442.                 PW = PWinitLTD + (maxNumLevelLTD-xPulse+i) * PWstepLTD;
  443.                 writeLatencyLTD += PW;
  444.                 writeVoltageSquareSum += V * V;
  445.             }
  446.             writePulseWidthLTD = writeLatencyLTD / (-numPulse);
  447.         }
  448.     }
  449.    
  450.     conductancePrev = conductance;
  451.     conductance = conductanceNew;
  452. }
  453.  
  454. /* Measured device */
  455. MeasuredDevice::MeasuredDevice(int x, int y) {
  456.     this->x = x; this->y = y;   // Cell location: x (column) and y (row) start from index 0
  457.     readVoltage = 0.5;  // On-chip read voltage (Vr) (V)
  458.     readPulseWidth = 5e-9;  // Read pulse width (s) (will be determined by ADC)
  459.     writeVoltageLTP = 2;    // Write voltage (V) for LTP or weight increase
  460.     writeVoltageLTD = 2;    // Write voltage (V) for LTD or weight decrease
  461.     writePulseWidthLTP = 100e-9;    // Write pulse width (s) for LTP or weight increase
  462.     writePulseWidthLTD = 100e-9;    // Write pulse width (s) for LTD or weight decrease
  463.     writeEnergy = 0;    // Dynamic variable for calculation of write energy (J)
  464.     numPulse = 0;   // Number of write pulses used in the most recent write operation (dynamic variable)
  465.     cmosAccess = true;  // True: Pseudo-crossbar (1T1R), false: cross-point
  466.     FeFET = false;      // True: FeFET structure (Pseudo-crossbar only, should be cmosAccess=1)
  467.     gateCapFeFET = 2.1717e-18;  // Gate capacitance of FeFET (F)
  468.     resistanceAccess = 15e3;    // The resistance of transistor (Ohm) in Pseudo-crossbar array when turned ON
  469.     nonlinearIV = false;    // Currently for cross-point array only
  470.     nonlinearWrite = false; // Consider weight update nonlinearity or not
  471.     nonIdenticalPulse = false;  // Use non-identical pulse scheme in weight update or not
  472.     if (nonIdenticalPulse) {
  473.         VinitLTP = 2.85;    // Initial write voltage for LTP or weight increase (V)
  474.         VstepLTP = 0.05;    // Write voltage step for LTP or weight increase (V)
  475.         VinitLTD = 2.1;     // Initial write voltage for LTD or weight decrease (V)
  476.         VstepLTD = 0.05;    // Write voltage step for LTD or weight decrease (V)
  477.         PWinitLTP = 75e-9;  // Initial write pulse width for LTP or weight increase (s)
  478.         PWstepLTP = 5e-9;   // Write pulse width for LTP or weight increase (s)
  479.         PWinitLTD = 75e-9;  // Initial write pulse width for LTD or weight decrease (s)
  480.         PWstepLTD = 5e-9;   // Write pulse width for LTD or weight decrease (s)
  481.         writeVoltageSquareSum = 0;  // Sum of V^2 of non-identical pulses (dynamic variable)
  482.     }
  483.     readNoise = false;      // Consider read noise or not
  484.     sigmaReadNoise = 0.0289;    // Sigma of read noise in gaussian distribution
  485.     NL = 10;    // Nonlinearity in write scheme (the current ratio between Vw and Vw/2), assuming for the LTP side
  486.     gaussian_dist = new std::normal_distribution<double>(0, sigmaReadNoise);    // Set up mean and stddev for read noise
  487.     symLTPandLTD = false;   // True: use LTP conductance data for LTD
  488.  
  489.     /* LTP */
  490.     double rawDataConductanceLTP[] = {0,1.00e-09,2.00e-09,3.00e-09,4.00e-09,5.00e-09,6.00e-09,7.00e-09,8.00e-09,9.00e-09,1.00e-08,1.10e-08,1.20e-08,1.30e-08,1.40e-08,1.50e-08,1.60e-08,1.70e-08,1.80e-08,1.90e-08,2.00e-08,2.10e-08,2.20e-08,2.30e-08,2.40e-08,2.50e-08,2.60e-08,2.70e-08,2.80e-08,2.90e-08,3.00e-08,3.10e-08,3.20e-08,3.30e-08,3.40e-08,3.50e-08,3.60e-08,3.70e-08,3.80e-08,3.90e-08,4.00e-08,4.10e-08,4.20e-08,4.30e-08,4.40e-08,4.50e-08,4.60e-08,4.70e-08,4.80e-08,4.90e-08,5.00e-08,5.10e-08,5.20e-08,5.30e-08,5.40e-08,5.50e-08,5.60e-08,5.70e-08,5.80e-08,5.90e-08,6.00e-08,6.10e-08,6.20e-08,6.30e-08};
  491.     dataConductanceLTP.insert(dataConductanceLTP.begin(), rawDataConductanceLTP, rawDataConductanceLTP + sizeof(rawDataConductanceLTP)/sizeof(rawDataConductanceLTP[0]));   // Put the raw data into a member variable of vector
  492.     maxNumLevelLTP = dataConductanceLTP.size() - 1;
  493.     /* LTD */
  494.     if (symLTPandLTD) { // Use LTP conductance data for LTD
  495.         for (int i=maxNumLevelLTP; i>=0; i--) {
  496.             dataConductanceLTD.push_back(dataConductanceLTP[i]);
  497.         }
  498.         maxNumLevelLTD = dataConductanceLTD.size() - 1;
  499.     } else {    // Use provided LTD conductance data
  500.         double rawDataConductanceLTD[] = {6.30e-08,6.20e-08,6.10e-08,6.00e-08,5.90e-08,5.80e-08,5.70e-08,5.60e-08,5.50e-08,5.40e-08,5.30e-08,5.20e-08,5.10e-08,5.00e-08,4.90e-08,4.80e-08,4.70e-08,4.60e-08,4.50e-08,4.40e-08,4.30e-08,4.20e-08,4.10e-08,4.00e-08,3.90e-08,3.80e-08,3.70e-08,3.60e-08,3.50e-08,3.40e-08,3.30e-08,3.20e-08,3.10e-08,3.00e-08,2.90e-08,2.80e-08,2.70e-08,2.60e-08,2.50e-08,2.40e-08,2.30e-08,2.20e-08,2.10e-08,2.00e-08,1.90e-08,1.80e-08,1.70e-08,1.60e-08,1.50e-08,1.40e-08,1.30e-08,1.20e-08,1.10e-08,1.00e-08,9.00e-09,8.00e-09,7.00e-09,6.00e-09,5.00e-09,4.00e-09,3.00e-09,2.00e-09,1.00e-09,0};
  501.         dataConductanceLTD.insert(dataConductanceLTD.begin(), rawDataConductanceLTD, rawDataConductanceLTD + sizeof(rawDataConductanceLTD)/sizeof(rawDataConductanceLTD[0]));   // Put the raw data into a member variable of vector
  502.         maxNumLevelLTD = dataConductanceLTD.size() - 1;
  503.     }
  504.     /* Define max/min/initial conductance */
  505.     maxConductance = (dataConductanceLTP.back() > dataConductanceLTD.front())? dataConductanceLTD.front() : dataConductanceLTP.back();      // The last conductance point of LTP or the first conductance point of LTD, depending on which one is smaller
  506.     minConductance = (dataConductanceLTP.front() > dataConductanceLTD.back())? dataConductanceLTP.front() : dataConductanceLTD.back();  // The first conductance point of LTP or the last conductance point of LTD, depending on which one is larger
  507.     avgMaxConductance = maxConductance; // Average maximum cell conductance (S)
  508.     avgMinConductance = minConductance; // Average minimum cell conductance (S)
  509.     conductance = minConductance;
  510.     conductancePrev = conductance;
  511.  
  512.     // Data check
  513.     /* Check if the conductance range of LTP and LTD are consistent */
  514.     if (dataConductanceLTP.back() != dataConductanceLTD.front() || dataConductanceLTP.front() != dataConductanceLTD.back()) {
  515.         puts("[Error] Conductance range of LTP and LTD are not consistent");
  516.         exit(-1);
  517.     }
  518.     /* Check if LTP conductance is monotonically increasing */
  519.     for (int i=1; i<=maxNumLevelLTP; i++) {
  520.         if (dataConductanceLTP[i] - dataConductanceLTP[i-1] <= 0) {
  521.             puts("[Error] LTP conductance should be monotonically increasing");
  522.             exit(-1);
  523.         }
  524.     }
  525.     /* Check if LTD conductance is monotonically decreasing */
  526.     for (int i=1; i<=maxNumLevelLTD; i++) {
  527.         if (dataConductanceLTD[i] - dataConductanceLTD[i-1] >= 0) {
  528.             puts("[Error] LTD conductance should be monotonically decreasing");
  529.             exit(-1);
  530.         }
  531.     }
  532.  
  533.     heightInFeatureSize = cmosAccess? 4 : 2;    // Cell height = 4F (Pseudo-crossbar) or 2F (cross-point)
  534.     widthInFeatureSize = cmosAccess? (FeFET? 6 : 4) : 2;    // Cell width = 6F (FeFET) or 4F (Pseudo-crossbar) or 2F (cross-point)
  535. }
  536.  
  537. double MeasuredDevice::Read(double voltage) {   // Return read current (A)
  538.     extern std::mt19937 gen;
  539.     if (nonlinearIV) {
  540.         // TODO: nonlinear read
  541.         if (readNoise) {
  542.             return voltage * conductance * (1 + (*gaussian_dist)(gen));
  543.         } else {
  544.             return voltage * conductance;
  545.         }
  546.     } else {
  547.         if (readNoise) {
  548.             return voltage * conductance * (1 + (*gaussian_dist)(gen));
  549.         } else {
  550.             return voltage * conductance;
  551.         }
  552.     }
  553. }
  554.  
  555. void MeasuredDevice::Write(double deltaWeightNormalized, double weight, double minWeight, double maxWeight) {
  556.     double conductanceNew;
  557.     if (deltaWeightNormalized > 0) {    // LTP
  558.         deltaWeightNormalized = deltaWeightNormalized/(maxWeight-minWeight);
  559.         deltaWeightNormalized = truncate(deltaWeightNormalized, maxNumLevelLTP);
  560.         numPulse = deltaWeightNormalized * maxNumLevelLTP;
  561.         if (nonlinearWrite) {
  562.             xPulse = InvMeasuredLTP(conductance, maxNumLevelLTP, dataConductanceLTP);
  563.             conductanceNew = MeasuredLTP(xPulse+numPulse, maxNumLevelLTP, dataConductanceLTP);
  564.         } else {
  565.             xPulse = (conductance - minConductance) / (maxConductance - minConductance) * maxNumLevelLTP;
  566.             conductanceNew = (weight-minWeight)/(maxWeight-minWeight) * (maxConductance - minConductance) + minConductance;
  567.             if (conductanceNew > maxConductance) {
  568.                 conductanceNew = maxConductance;
  569.             }
  570.         }
  571.     } else {    // LTD
  572.         deltaWeightNormalized = deltaWeightNormalized/(maxWeight-minWeight);
  573.         deltaWeightNormalized = truncate(deltaWeightNormalized, maxNumLevelLTD);
  574.         numPulse = deltaWeightNormalized * maxNumLevelLTD;
  575.         if (nonlinearWrite) {
  576.             xPulse = InvMeasuredLTP(conductance, maxNumLevelLTP, dataConductanceLTP);
  577.             conductanceNew = MeasuredLTP(xPulse+numPulse, maxNumLevelLTP, dataConductanceLTP);  // Use xPulse-numPulse here because the conductance will decrease with larger pulse position in dataConductanceLTD
  578.         } else {
  579.             xPulse = (conductance - minConductance) / (maxConductance - minConductance) * maxNumLevelLTD;
  580.             conductanceNew = (weight-minWeight)/(maxWeight-minWeight) * (maxConductance - minConductance) + minConductance;
  581.             if (conductanceNew < minConductance) {
  582.                 conductanceNew = minConductance;
  583.             }
  584.         }
  585.     }
  586.  
  587.     /* Write latency calculation */
  588.     if (!nonIdenticalPulse) {   // Identical write pulse scheme
  589.         if (numPulse > 0) { // LTP
  590.             writeLatencyLTP = numPulse * writePulseWidthLTP;
  591.             writeLatencyLTD = 0;
  592.         } else {    // LTD
  593.             writeLatencyLTP = 0;
  594.             writeLatencyLTD = -numPulse * writePulseWidthLTD;
  595.         }
  596.     } else {    // Non-identical write pulse scheme
  597.         writeLatencyLTP = 0;
  598.         writeLatencyLTD = 0;
  599.         writeVoltageSquareSum = 0;
  600.         double V = 0;
  601.         double PW = 0;
  602.         if (numPulse > 0) { // LTP
  603.             for (int i=0; i<numPulse; i++) {
  604.                 V = VinitLTP + (xPulse+i) * VstepLTP;
  605.                 PW = PWinitLTP + (xPulse+i) * PWstepLTP;
  606.                 writeLatencyLTP += PW;
  607.                 writeVoltageSquareSum += V * V;
  608.             }
  609.             writePulseWidthLTP = writeLatencyLTP / numPulse;
  610.         } else {    // LTD
  611.             for (int i=0; i<(-numPulse); i++) {
  612.                 V = VinitLTD + (maxNumLevelLTD-xPulse+i) * VstepLTD;
  613.                 PW = PWinitLTD + (maxNumLevelLTD-xPulse+i) * PWstepLTD;
  614.                 writeLatencyLTD += PW;
  615.                 writeVoltageSquareSum += V * V;
  616.             }
  617.             writePulseWidthLTD = writeLatencyLTD / (-numPulse);
  618.         }
  619.     }
  620.  
  621.     conductancePrev = conductance;
  622.     conductance = conductanceNew;
  623. }
  624.  
  625. /* SRAM */
  626. SRAM::SRAM(int x, int y) {
  627.     this->x = x; this->y = y;
  628.     bit = 0;    // Stored bit (1 or 0) (dynamic variable)
  629.     bitPrev = 0;    // Previous bit
  630.     heightInFeatureSize = 14.6; // Cell height in terms of feature size (F)
  631.     widthInFeatureSize = 10;    // Cell width in terms of feature size (F)
  632.     widthSRAMCellNMOS = 2.08;   // Pull-down NMOS width in terms of feature size (F)
  633.     widthSRAMCellPMOS = 1.23;   // Pull-up PMOS width in terms of feature size (F)
  634.     widthAccessCMOS = 1.31;     // Access transistor width in terms of feature size (F)
  635.     minSenseVoltage = 0.1;      // Minimum voltage difference (V) for sensing
  636.     readEnergy = 0;             // Dynamic variable for calculation of read energy (J)
  637.     writeEnergy = 0;            // Dynamic variable for calculation of write energy (J)
  638.     readEnergySRAMCell = 0;     // Read energy (J) per SRAM cell (currently not used, it is included in the peripheral circuits of SRAM array in NeuroSim)
  639.     writeEnergySRAMCell = 0;    // Write energy (J) per SRAM cell (will be obtained from NeuroSim)
  640. }
  641.  
  642. /* Digital eNVM */
  643. DigitalNVM::DigitalNVM(int x, int y) {
  644.     this->x = x; this->y = y;   // Cell location: x (column) and y (row) start from index 0
  645.     bit = 0;    // Stored bit (1 or 0) (dynamic variable), for internel check only and not be used for read
  646.     bitPrev = 0;    // Previous bit
  647.     maxConductance = 5e-6;      // Maximum cell conductance (S)
  648.     minConductance = 100e-9;    // Minimum cell conductance (S)
  649.     avgMaxConductance = maxConductance; // Average maximum cell conductance (S)
  650.     avgMinConductance = minConductance; // Average minimum cell conductance (S)
  651.     conductance = minConductance;   // Current conductance (S) (dynamic variable)
  652.     conductancePrev = conductance;  // Previous conductance (S) (dynamic variable)
  653.     readVoltage = 0.5;  // On-chip read voltage (Vr) (V)
  654.     readPulseWidth = 5e-9;  // Read pulse width (s) (will be determined by S/A)
  655.     writeVoltageLTP = 2.5;  // Write voltage (V) for LTP or weight increase
  656.     writeVoltageLTD = 2.5;  // Write voltage (V) for LTD or weight decrease
  657.     writePulseWidthLTP = 10e-9; // Write pulse width (s) for LTP or weight increase
  658.     writePulseWidthLTD = 10e-9; // Write pulse width (s) for LTD or weight decrease
  659.     readEnergy = 0;     // Read pulse width (s) (currently not used)
  660.     writeEnergy = 0;    // Dynamic variable for calculation of write energy (J)
  661.     cmosAccess = true;  // True: Pseudo-crossbar (1T1R), false: cross-point
  662.     parallelRead = false; // if it is a parallel readout scheme
  663.     resistanceAccess = 15e3;    // The resistance of transistor (Ohm) in Pseudo-crossbar array when turned ON
  664.     nonlinearIV = false;    // Consider I-V nonlinearity or not (Currently for cross-point array only)
  665.     NL = 10;    // Nonlinearity in write scheme (the current ratio between Vw and Vw/2), assuming for the LTP side
  666.     if (nonlinearIV) {  // Currently for cross-point array only
  667.         double Vr_exp = readVoltage;  // XXX: Modify this value to Vr in the reported measurement data (can be different than readVoltage)
  668.         // Calculation of conductance at on-chip Vr
  669.         maxConductance = NonlinearConductance(maxConductance, NL, writeVoltageLTP, Vr_exp, readVoltage);
  670.         minConductance = NonlinearConductance(minConductance, NL, writeVoltageLTP, Vr_exp, readVoltage);
  671.     }
  672.     readNoise = false;      // Consider read noise or not
  673.     sigmaReadNoise = 0.25;  // Sigma of read noise in gaussian distribution
  674.     gaussian_dist = new std::normal_distribution<double>(0, sigmaReadNoise);    // Set up mean and stddev for read noise
  675.   if(cmosAccess){ // the reference current for 1T1R cell, should include the resistance
  676.       double Rmax=1/maxConductance;
  677.       double Rmin=1/minConductance;
  678.       refCurrent = readVoltage/(0.5*(Rmax+Rmin+2*resistanceAccess));
  679.   }
  680.   else { // the reference current for cross-point array
  681.       refCurrent = readVoltage * (avgMaxConductance + avgMinConductance) / 2;   // Set up reference current for sensing      
  682.   }
  683.  
  684.     /* Conductance range variation */
  685.     conductanceRangeVar =false;    // Consider variation of conductance range or not
  686.     maxConductanceVar = 0.01*maxConductance;  // Sigma of maxConductance variation (S)
  687.     minConductanceVar = 0.01*minConductance;  // Sigma of minConductance variation (S)
  688.     std::mt19937 localGen;
  689.     localGen.seed(std::time(0));
  690.     gaussian_dist_maxConductance = new std::normal_distribution<double>(0, maxConductanceVar);
  691.     gaussian_dist_minConductance = new std::normal_distribution<double>(0, minConductanceVar);
  692.     if (conductanceRangeVar) {
  693.         maxConductance += (*gaussian_dist_maxConductance)(localGen);
  694.         minConductance += (*gaussian_dist_minConductance)(localGen);
  695.     if (minConductance >= maxConductance || maxConductance < 0 || minConductance < 0 ) {    // Conductance variation check
  696.             puts("[Error] Conductance variation check not passed. The variation may be too large.");
  697.             exit(-1);
  698.         }
  699.     }
  700.  
  701.     heightInFeatureSize = cmosAccess? 4 : 2;    // Cell height = 4F (1T1R) or 2F (cross-point)
  702.     widthInFeatureSize = cmosAccess? 4 : 2; // Cell width = 4F (1T1R) or 2F (cross-point)
  703. }
  704.  
  705. double DigitalNVM::Read(double voltage) {   // Return read current (A)
  706.     extern std::mt19937 gen;
  707.     if (nonlinearIV) {
  708.         // TODO: nonlinear read
  709.         if (readNoise) {
  710.             return voltage * conductance * (1 + (*gaussian_dist)(gen));
  711.         } else {
  712.             return voltage * conductance;
  713.         }
  714.     } else {
  715.         if (readNoise) {
  716.             return voltage * conductance * (1 + (*gaussian_dist)(gen));
  717.         } else {
  718.             return voltage * conductance;
  719.         }
  720.     }
  721. }
  722.  
  723. void DigitalNVM::Write(int bitNew, double wireCapCol) {
  724.     double conductanceNew;
  725.     if (nonlinearIV) {  // Currently only for cross-point array
  726.         if (bitNew == 1) {  // SET
  727.             conductanceNew = maxConductance;
  728.         } else {    // RESET
  729.             conductanceNew = minConductance;
  730.         }
  731.         /* I-V nonlinearity */
  732.         conductanceAtVwLTP = NonlinearConductance(conductance, NL, writeVoltageLTP, readVoltage, writeVoltageLTP);
  733.         conductanceAtHalfVwLTP = NonlinearConductance(conductance, NL, writeVoltageLTP, readVoltage, writeVoltageLTP/2);
  734.         conductanceAtVwLTD = NonlinearConductance(conductance, NL, writeVoltageLTD, readVoltage, writeVoltageLTD);
  735.         conductanceAtHalfVwLTD = NonlinearConductance(conductance, NL, writeVoltageLTD, readVoltage, writeVoltageLTD/2);
  736.         double conductanceNewAtVwLTP = NonlinearConductance(conductanceNew, NL, writeVoltageLTP, readVoltage, writeVoltageLTP);
  737.         double conductanceNewAtHalfVwLTP = NonlinearConductance(conductanceNew, NL, writeVoltageLTP, readVoltage, writeVoltageLTP/2);
  738.         double conductanceNewAtVwLTD = NonlinearConductance(conductanceNew, NL, writeVoltageLTD, readVoltage, writeVoltageLTD);
  739.         double conductanceNewAtHalfVwLTD = NonlinearConductance(conductanceNew, NL, writeVoltageLTD, readVoltage, writeVoltageLTD/2);
  740.         if (bitNew == 1 && bit == 0) {  // SET
  741.             writeEnergy = writeVoltageLTP * writeVoltageLTP * (conductanceAtVwLTP + conductanceNewAtVwLTP)/2 * writePulseWidthLTP;    // Selected cell in SET phase
  742.             writeEnergy += writeVoltageLTP * writeVoltageLTP * wireCapCol;  // Charging the cap of selected columns
  743.             writeEnergy += writeVoltageLTD/2 * writeVoltageLTD/2 * conductanceNewAtHalfVwLTD * writePulseWidthLTD;    // Half-selected during RESET phase (use the new conductance value if SET phase is before RESET phase)
  744.             writeEnergy += writeVoltageLTD/2 * writeVoltageLTD/2 * wireCapCol;
  745.         } else if (bitNew == 0 && bit == 1) {    // RESET
  746.             writeEnergy = writeVoltageLTP/2 * writeVoltageLTP/2 * conductanceAtHalfVwLTP * writePulseWidthLTP; // Half-selected during SET phase (use the old conductance value if SET phase is before RESET phase)
  747.             writeEnergy += writeVoltageLTP/2 * writeVoltageLTP/2 * wireCapCol;
  748.             writeEnergy += writeVoltageLTD * writeVoltageLTD * wireCapCol;  // Charging the cap of selected columns
  749.             writeEnergy += writeVoltageLTD * writeVoltageLTD * (conductanceAtVwLTD + conductanceNewAtVwLTD)/2 * writePulseWidthLTD;    // Selected cell in RESET phase
  750.         } else {    // Half-selected
  751.             writeEnergy = writeVoltageLTP/2 * writeVoltageLTP/2 * conductanceAtHalfVwLTP * writePulseWidthLTP; // Half-selected during SET phase
  752.             writeEnergy += writeVoltageLTP/2 * writeVoltageLTP/2 * wireCapCol;
  753.             writeEnergy += writeVoltageLTD/2 * writeVoltageLTD/2 * conductanceAtHalfVwLTD * writePulseWidthLTD; // Half-selected during RESET phase
  754.             writeEnergy += writeVoltageLTD/2 * writeVoltageLTD/2 * wireCapCol;
  755.         }
  756.         /* Update the nonlinear conductances with new values */
  757.         conductanceAtVwLTP = conductanceNewAtVwLTP;
  758.         conductanceAtHalfVwLTP = conductanceNewAtHalfVwLTP;
  759.         conductanceAtVwLTD = conductanceNewAtVwLTD;
  760.         conductanceAtHalfVwLTD = conductanceNewAtHalfVwLTD;
  761.     } else {    // If not cross-point array or not considering I-V nonlinearity
  762.         if (bitNew == 1 && bit == 0) {  // SET
  763.             /* Normal 1T1R */
  764.             conductanceNew = maxConductance;
  765.             writeEnergy = writeVoltageLTP * writeVoltageLTP * (conductance + conductanceNew)/2 * writePulseWidthLTP;    // Selected cell in SET phase
  766.             writeEnergy += writeVoltageLTP * writeVoltageLTP * wireCapCol;  // Charging the cap of selected columns
  767.             if (!cmosAccess) {  // Cross-point
  768.                 writeEnergy += writeVoltageLTD/2 * writeVoltageLTD/2 * conductanceNew * writePulseWidthLTD;    // Half-selected during RESET phase (use the new conductance value if SET phase is before RESET phase)
  769.                 writeEnergy += writeVoltageLTD/2 * writeVoltageLTD/2 * wireCapCol;
  770.             }
  771.         } else if (bitNew == 0 && bit == 1) {   // RESET
  772.             /* Normal 1T1R */
  773.             conductanceNew = minConductance;
  774.             writeEnergy = writeVoltageLTD * writeVoltageLTD * (conductance + conductanceNew)/2 * writePulseWidthLTD;    // Selected cell in RESET phase
  775.             writeEnergy += writeVoltageLTD * writeVoltageLTD * wireCapCol;  // Charging the cap of selected columns
  776.             if (!cmosAccess) {  // Cross-point
  777.                 writeEnergy += writeVoltageLTP/2 * writeVoltageLTP/2 * conductance * writePulseWidthLTP;    // Half-selected during SET phase (use the old conductance value if SET phase is before RESET phase)
  778.                 writeEnergy += writeVoltageLTP/2 * writeVoltageLTP/2 * wireCapCol;
  779.             }
  780.         } else {    // No operation
  781.             conductanceNew = (bitNew == 1)? maxConductance : minConductance;
  782.         }
  783.     }
  784.     conductancePrev = conductance;
  785.     conductance = conductanceNew;
  786.     bitPrev = bit;
  787.     bit = bitNew;
  788. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement