예제 #1
0
파일: rram.py 프로젝트: botimerj/1Rx
class RRAM:
    def __init__(self, gp):
        # Global Parameters
        self.gp = gp

        # RRAM Parameters
        self.ron = gp.rram.ron
        self.roff = gp.rram.roff
        self.rvar = gp.rram.rvar
        self.rp = gp.rram.rp

        self.vdiff = gp.rram.von - gp.rram.voff

        self.n_bit = gp.rram.n_bit
        self.rlsb = (self.roff - self.ron) / (2**self.n_bit - 1)
        self.glsb = (1 / self.ron - 1 / self.roff) / (2**self.n_bit - 1)

        self.x = gp.rram.size_x
        self.y = gp.rram.size_y

        # Resistance values
        self.arr = np.empty([self.y, self.x])

        # Digital values
        self.dig_arr = np.empty([self.y, self.x])

        # ADC
        self.adc = ADC(gp, self.n_bit, gp.mvm.active_rows,\
                       self.ron, self.roff, self.rvar, self.vdiff)

        # Energy
        self.e_read = 0

    def write(self, weights, res):
        # Helper variables
        n_bit = int(self.n_bit)
        n_cell = int(np.ceil(res / n_bit))
        if (n_cell > self.x):
            raise Exception("No weight splitting allowed")

        w = np.array(weights, dtype=int)

        # Generate digital represntation in weight arr
        self.dig_arr = np.zeros([self.y, self.x])
        for i in range(w.shape[0]):
            for j in range(w.shape[1]):
                try:
                    num = int(w[i][j])
                    a = [(num >> (n_bit * i)) & (2**n_bit - 1)
                         for i in range(n_cell)]
                    a = np.flip(np.array(a, dtype=int))
                    self.dig_arr[i][j * n_cell:(j + 1) * n_cell] = a
                except:
                    print("except")
                    pass

        # Assign real resistances to r_cell
        for i in range(self.y):
            for j in range(self.x):
                self.arr[i][j] = 1 / self.roff + self.glsb * self.dig_arr[i][j]

                self.arr[i][j] = 1 / (10**(np.log10(1 / self.arr[i][j]) +
                                           np.random.normal(0, self.rvar)))
                #self.arr[i][j]  = 1/(1/self.arr[i][j] + np.random.normal(0,self.rvar))
                #print(1/self.arr[i][j])

    def read(self, ifmap, res):

        ifm = np.array(ifmap, dtype=int)

        # Bit-serial approach
        dout = np.zeros([1, self.x])
        for i in range(res):
            v = ((ifm >> i) & 1) * (self.vdiff)
            i_out = np.dot(v, self.arr)
            for j in range(self.x):
                dout[0, j] = dout[0, j] + (self.adc.convert(i_out[j]) << i)
                self.e_read += self.adc.energy

        dout = np.array(dout, dtype=int)

        # Concatenate columns
        n_cell = int(np.ceil(res / self.n_bit))
        num_words = int(np.floor(self.x / n_cell))

        out = np.zeros([1, num_words])
        for i in range(num_words):
            for j in range(n_cell):
                idx = i * n_cell + j
                out[0][i] += (dout[0][idx] << ((n_cell - 1 - j) * self.n_bit))

        return out