예제 #1
0
 def _initSrRestore(self):
     # SRs
     self.I1_SR = IC.ShiftRegister(name='I1-SR')
     self.I2_SR = IC.ShiftRegister(name='I2-SR')
     # AND write and clk to know when to shift in
     I1_SR_CLK = asyncIC.AND(1)
     I2_SR_CLK = asyncIC.AND(1)
     I1_SR_CLK.wire(
         self.node_done.output, self.I2_RD
     )  # Active when its EEPROM is being written to (OTHER EEPROM IS BEING READ FROM)
     I2_SR_CLK.wire(self.node_done.output, self.I1_RD)
     # Wire input of SRs to LSB of accum
     i = self.accum.width
     MSB = self.accum.output[i - 1:i]  # Take the MSB
     quantI = asyncIC.NOT(name='Accum-Quantized')
     quantI.wire(MSB)
     # Wire input of SRs
     self.I1_SR.wire(quantI.output, I1_SR_CLK.output)
     self.I2_SR.wire(quantI.output, I2_SR_CLK.output)
     # Flash pins (activates when node_counter % 8 == 0 (3 LSB == 0))
     self.input_flash = asyncIC.bitNOR(3, name='INPUT-FLASH')
     self.input_flash.wire(self.node_counter[0:3])
     self.input_flash_delayed = IC.FlipFlop(1, name='INPUT-FLASH #1')
     self.input_flash_delayed.wire(self.input_flash.output,
                                   self.node_done.output)
     # Reverse output of SR because data is loaded in backwards
     self.I1_SR_OUT = self.I1_SR.output[::-1]
     self.I2_SR_OUT = self.I2_SR.output[::-1]
예제 #2
0
 def _initCounters(self):
     # Sizes should match those of EEPROMS
     self.layer_counter = IC.Counter(BITS_LAYER, name='L-COUNT')
     self.node_counter = IC.Counter(10, name='N-COUNT')
     self.weight_counter = IC.Counter(10, name='W-COUNT')
     # * Comparison outputs to notify when to increment
     self.model_done = asyncIC.IdentityComparator(10, name='M-DONE')
     self.layer_done = asyncIC.IdentityComparator(10, name='L-DONE')
     self.node_done = asyncIC.IdentityComparator(10, name='N-DONE')
     # Wire to inputs
     zero = asyncIC.pins(10, name='GND')
     self.model_done.wire(
         self.LAYER_SIZE.output,
         zero)  # HW - default in shape EEPROM is 0xFF, not ground
     self.layer_done.wire(self.node_counter.output, self.LAYER_SIZE.output)
     self.node_done.wire(self.weight_counter.output, self.INPUT_SIZE.output)
     # Wire to each other
     self.node_counter.wire(clk=self.node_done.output)
     self.layer_counter.wire(clk=self.layer_done.output)
     # Create delayed signal for shifting the shape
     self.layer_done_delayed = IC.FlipFlop(1, name='L-DONE #1')
     self.layer_done_delayed.wire(self.layer_done.output, self.clk)
     self.layer_done_delayed = self.layer_done_delayed.output
     # Wire SHAPE output
     self.INPUT_SIZE.wire(self.LAYER_SIZE.output,
                          self.layer_done_delayed)  # ? clk order matters?
     self.LAYER_SIZE.wire(self.SHAPE_EEPROM.output, self.layer_done_delayed
                          )  # ! Wire to init clock OR'd with layer_done
예제 #3
0
 def _initChips(self):
     # EEPROM that stores the values
     self.FINAL_EEPROM = asyncIC.EEPROM(addr_len=7, name='EE-Data')
     # Index to iterate throught the logits
     self.index = IC.Counter(7, name='Index')
     # Flip flop to store the current macimum value seen and it's index (answer)
     self.max_val = IC.FlipFlop(8, name='Max-Val')
     self.max_index = IC.FlipFlop(7, name='Max-Index')
     # Compares current value to max_val, and loads it if it is higher (along with the index)
     self.val_comp = asyncIC.MagnitudeComparator(8, name='Val-Comp')
     self.is_greater = self.val_comp[0:1]
     # Clock (Increments index)
     self.clk = IC.CLOCK()
예제 #4
0
 def _initEEPROMs(self):
     # Weights currently require 98 kB : addr_len >= 17 if packed to the max
     self.WEIGHTS_EEPROM = asyncIC.EEPROM(addr_len=18, name='WEIGHTS')
     # * Current model max dimensions - # of: layers=2, nodes=512, weights-bytes-in-node=98
     # MINIMUM address bits for current model - 1, 9, 7
     self.WEIGHTS_EEPROM.fill3D(weights,
                                (BITS_LAYER, BITS_NODES, BITS_WEIGHTS))
     # Alternating data EEPROMs
     self.INPUT1_EEPROM = asyncIC.EEPROM(addr_len=7, name='INPUT1')
     self.INPUT2_EEPROM = asyncIC.EEPROM(addr_len=7,
                                         name='INPUT2')  # ? Storage EEPROM
     # MINIMUM address bits for current model - 2 (784, 512, 10)
     self.SHAPE_EEPROM = asyncIC.EEPROM(addr_len=2, io_len=10, name='SHAPE')
     self.SHAPE_EEPROM.fill(shape)
     self.INPUT_SIZE = IC.FlipFlop(10, val=784, name='SHAPE_WEIGHT_COUNT')
     self.LAYER_SIZE = IC.FlipFlop(10, val=512, name='SHAPE_NODE_COUNT')
예제 #5
0
 def _initRDSignals(self):
     # LSB of layer counter choose between EEPROMs
     self.I2_RD = self.layer_counter[
         0:
         1]  # 0: READ INPUT1, 1: READ INPUT2 (read from 1 first - it has the image)
     self.I2_RD.name = 'I2-Read'
     # Other RD single is the opposite of I1-RD
     I1_RD = asyncIC.NOT(1, name='I1-Read')
     I1_RD.wire(self.I2_RD)
     self.I1_RD = I1_RD.output
     # RD_WR needs to be delayed one clk cycle (HW - Combine these into one flipflop)
     self.I1_RD_delayed = IC.FlipFlop(1, name='I1-Read (#1)')
     self.I1_RD_delayed.wire(self.I1_RD, self.clk)
     self.I2_RD_delayed = IC.FlipFlop(1, name='I2-Read (#1)')
     self.I2_RD_delayed.wire(self.I2_RD, self.clk)
     # Reference the output pins
     self.I1_RD_delayed = self.I1_RD_delayed.output
     self.I2_RD_delayed = self.I2_RD_delayed.output
예제 #6
0
 def _finalEEPROM(self):
     self.FINAL_EEPROM = asyncIC.EEPROM(addr_len=10,
                                        io_len=10,
                                        name='FINAL')
     # Rd/wr signal
     self.model_not_done = asyncIC.NOT(name='NOT M-DONE')
     self.model_not_done.wire(self.model_done.output)
     # Delayed address
     self.node_counter_delayed = IC.FlipFlop(10, name='N-COUNT #1')
     self.node_counter_delayed.wire(self.node_counter.output, clk=self.clk)
     # Wiring
     self.FINAL_EEPROM.wire(self.node_counter_delayed.output,
                            self.accum.output, self.model_not_done.output,
                            self.node_done.output)
예제 #7
0
 def _initMult(self):
     # MUXs
     self.W_OUT_MUX = asyncIC.bitMux(name='Weights-Mux')
     self.I1_OUT_MUX = asyncIC.bitMux(name='I1-Out-Mux')
     self.I2_OUT_MUX = asyncIC.bitMux(name='I2-Out-Mux')
     # Select between the output of the two EEPROMS
     self.I_TOT_MUX = asyncIC.Mux(1, name='Final-Input-Mux')
     self.I_TOT_MUX.wire(self.I2_OUT_MUX.output, self.I1_OUT_MUX.output,
                         self.I1_RD)
     # MULTIPLIER
     self.XNOR = asyncIC.XNOR(name='Multiplier')
     self.XNOR.wire(self.W_OUT_MUX.output, self.I_TOT_MUX.output)
     # ADDER
     self.accum = IC.UpDownCounter(10, name='Accum')
     self.accum.wire(self.XNOR.output)
예제 #8
0
    def __init__(self):
        self.bar = True  # Display variable
        self.clk = IC.CLOCK()

        self._initEEPROMs()
        self._initCounters()
        self._initRDSignals()
        self._initMult()
        self._initSrRestore()
        self._initAddrRestore()
        self._wireEEPROM()
        self._finalEEPROM()

        self.clk.sync([
            self.accum,
            self.weight_counter,
        ])
예제 #9
0
 def _initAddrRestore(self):
     # Rearrange outputting address lines
     weight_incr = self.weight_counter[3:10]  # 7 pins
     self.w_addr = asyncIC.pins(
         pins_list=(weight_incr, self.node_counter[0:9],
                    self.layer_counter.output))  # 17 pins
     # Input EEPROMs address deciding
     self.i_addr_active = weight_incr
     self.i_addr_active.name = 'I-ADDR-AC'
     self.i_addr_listen = IC.FlipFlop(
         7, name='I-ADDR-LS'
     )  # 7 pins (Flipflop inbetween mux and node_counter // 8 to delay the signal)
     self.i_addr_listen.wire(self.node_counter[3:10],
                             clk=self.clk)  # Updates every clock cycle
     # MUXs to select between the two possible address lines
     self.I1_ADDR_MUX = asyncIC.Mux(7, name='I1-ADDR-MUX')
     self.I2_ADDR_MUX = asyncIC.Mux(7, name='I2-ADDR-MUX')
     # MUX selection wiring
     self.I1_ADDR_MUX.wire(self.i_addr_listen.output, self.i_addr_active,
                           self.I1_RD_delayed)
     self.I2_ADDR_MUX.wire(self.i_addr_listen.output, self.i_addr_active,
                           self.I2_RD_delayed)