def test_min_spl1_should_allow_external_input_on_same_chip(self): """ Even when the rightmost neuron block / DNC merger is not reserved for external input, it should be possible to place external input on the same chip. """ pynn.setup(marocco=self.marocco) neuron_size = 4 self.marocco.neuron_placement.default_neuron_size(neuron_size) self.marocco.merger_routing.strategy( self.marocco.merger_routing.minimize_number_of_sending_repeaters) # Do not reserve rightmost neuron block / DNC merger for external input. self.marocco.neuron_placement.restrict_rightmost_neuron_blocks(False) hicann = C.HICANNOnWafer(C.Enum(123)) pops = [] # All but the first neuron block are occupied. for nb in range(1, C.NeuronBlockOnHICANN.end): pop = pynn.Population(1, pynn.IF_cond_exp, {}) self.marocco.manual_placement.on_neuron_block( pop, C.NeuronBlockOnWafer(C.NeuronBlockOnHICANN(nb), hicann)) pops.append(pop) in_pop = pynn.Population(1, pynn.SpikeSourceArray, {}) self.marocco.manual_placement.on_hicann(in_pop, hicann) pynn.run(0) pynn.end() results = self.load_results() for pop in pops: nrn = pop[0] placement_item, = results.placement.find(nrn) logical_neuron = placement_item.logical_neuron() self.assertEqual(neuron_size, logical_neuron.size()) for denmem in logical_neuron: self.assertEqual(hicann, denmem.toHICANNOnWafer()) address = placement_item.address() # All used neuron blocks should be connected to a single DNC merger. dnc = C.DNCMergerOnHICANN(3) self.assertEqual(hicann, address.toHICANNOnWafer()) self.assertEqual(dnc, address.toDNCMergerOnHICANN()) self.assertEqual(C.DNCMergerOnWafer(dnc, hicann), address.toDNCMergerOnWafer()) nrn = in_pop[0] placement_item, = results.placement.find(nrn) logical_neuron = placement_item.logical_neuron() self.assertTrue(logical_neuron.is_external()) address = placement_item.address() # External input should be on the leftmost DNC merger, since all other # mergers do not have direct access to a background generator. dnc = C.DNCMergerOnHICANN(0) self.assertEqual(hicann, address.toHICANNOnWafer()) self.assertEqual(dnc, address.toDNCMergerOnHICANN()) self.assertEqual(C.DNCMergerOnWafer(dnc, hicann), address.toDNCMergerOnWafer())
def test_min_spl1_is_nongreedy_when_pops_are_placed_to_nbs(self, nbs): """ See above. Instead of a single population placed to the HICANN, populations are placed to specific neuron blocks. """ pynn.setup(marocco=self.marocco) neuron_size = 4 self.marocco.neuron_placement.default_neuron_size(neuron_size) self.marocco.merger_routing.strategy( self.marocco.merger_routing.minimize_number_of_sending_repeaters) self.marocco.neuron_placement.restrict_rightmost_neuron_blocks(True) hicann = C.HICANNOnWafer(C.Enum(123)) pops = [] for nb in nbs: pop = pynn.Population(1, pynn.IF_cond_exp, {}) self.marocco.manual_placement.on_neuron_block( pop, C.NeuronBlockOnWafer(C.NeuronBlockOnHICANN(nb), hicann)) pops.append(pop) in_pop = pynn.Population(1, pynn.SpikeSourceArray, {}) self.marocco.manual_placement.on_hicann(in_pop, hicann) pynn.run(0) pynn.end() results = self.load_results() for pop in pops: nrn = pop[0] placement_item, = results.placement.find(nrn) logical_neuron = placement_item.logical_neuron() self.assertEqual(neuron_size, logical_neuron.size()) for denmem in logical_neuron: self.assertEqual(hicann, denmem.toHICANNOnWafer()) address = placement_item.address() # All used neuron blocks should still be connected to a single DNC merger. dnc = C.DNCMergerOnHICANN(3) self.assertEqual(hicann, address.toHICANNOnWafer()) self.assertEqual(dnc, address.toDNCMergerOnHICANN()) self.assertEqual(C.DNCMergerOnWafer(dnc, hicann), address.toDNCMergerOnWafer()) nrn = in_pop[0] placement_item, = results.placement.find(nrn) logical_neuron = placement_item.logical_neuron() self.assertTrue(logical_neuron.is_external()) address = placement_item.address() # External input should be on the rightmost DNC merger since that is tried first. dnc = C.DNCMergerOnHICANN(7) self.assertEqual(hicann, address.toHICANNOnWafer()) self.assertEqual(dnc, address.toDNCMergerOnHICANN()) self.assertEqual(C.DNCMergerOnWafer(dnc, hicann), address.toDNCMergerOnWafer())
def test_BGToNeuronMembrane(self): """Try to send periodic events from a background generator to a neuron. Please note that this test relies on the default config values in most objects and only changes those necessary to run the test.""" weight = 15 period = 700 * 2 event = HICANN.L1Address(0) offevent = HICANN.L1Address(55) trace_length = 19500 exc = True inh = False E_syn = (570, 570) firing = False firingevent = HICANN.L1Address(42) # FIXME: Differs from HICANN to HICANN, this needs connection database analog = Coordinate.AnalogOnHICANN(1) adc_channel = 7 neuron = Coordinate.NeuronOnHICANN(Enum(15)) vline = Coordinate.VLineOnHICANN(28) # or 60, 92, 124 driver = Coordinate.SynapseDriverOnHICANN(Y(111), left) synapse_row = Coordinate.SynapseRowOnHICANN(driver, top) ############################## # set floating gate values # ############################## fgcfg = HICANN.FGConfig() fgctrl = HICANN.FGControl() # Set same reverse potential for both synaptic inputs (for all neurons) for ii in range(512): nrn = Coordinate.NeuronOnHICANN(Enum(ii)) fgctrl.setNeuron(nrn, HICANN.neuron_parameter.E_synx, E_syn[0]) fgctrl.setNeuron(nrn, HICANN.neuron_parameter.E_syni, E_syn[1]) fgctrl.setNeuron(nrn, HICANN.neuron_parameter.I_bexp, 0) for block in Coordinate.iter_all(Coordinate.FGBlockOnHICANN): HICANN.set_fg_config(self.h, block, fgcfg) HICANN.set_fg_values(self.h, fgctrl) ############################## # set global neuron config # ############################## nconf = HICANN.NeuronConfig() nconf.bigcap[int(top)] = True nconf.bigcap[int(bottom)] = True HICANN.set_neuron_config(self.h, nconf) ################# # set mergers # ################# dnc = HICANN.DNCMergerLine() for i in range(8): mer = Coordinate.DNCMergerOnHICANN(i) dnc[mer].slow = True dnc[mer].config = HICANN.Merger.RIGHT_ONLY # Tree defaults to one on one passthrough (forward downwards) tree = HICANN.MergerTree() HICANN.set_dnc_merger(self.h, dnc) HICANN.set_merger_tree(self.h, tree) ########################## # background generator # ########################## # We use one background generator to provide events gens = HICANN.BackgroundGeneratorArray() g = gens[7] g.enable(True) g.random(False) g.period(period) g.address(event) HICANN.set_background_generator(self.h, gens) # Forward its output to this HICANN srepeater = Coordinate.OutputBufferOnHICANN(7).repeater() sr = HICANN.HorizontalRepeater() sr.setOutput(right) HICANN.set_repeater(self.h, srepeater.horizontal(), sr) ############################################### # connect via Crossbars and SynapseSwitches # ############################################### hline = srepeater.toHLineOnHICANN() cb = HICANN.Crossbar() cb.set(vline, hline, True) HICANN.set_crossbar_switch_row( self.h, hline, vline.toSideHorizontal(), cb.get_row(hline, vline.toSideHorizontal())) # Connect VLine to synapse driver sw = HICANN.SynapseSwitch() sw.set(vline, driver.toHLineOnHICANN(), True) HICANN.set_syndriver_switch_row( self.h, driver.toSynapseSwitchRowOnHICANN(), sw.get_row(driver.toSynapseSwitchRowOnHICANN())) ######################## # set synapse driver # ######################## drv = HICANN.SynapseDriver() drv.set_l1() drv[top].set_syn_in(left, exc) drv[top].set_syn_in(right, inh) drv[bottom].set_syn_in(left, exc) drv[bottom].set_syn_in(right, inh) HICANN.set_synapse_driver(self.h, driver, drv) decoders = HICANN.DecoderDoubleRow() weights = HICANN.WeightRow() # Reset decoders and weights to 'off' state for ii in range(2): for jj in range(256): decoders[ii][jj] = offevent.getSynapseDecoderMask() for ii in range(256): weights[ii] = 0 # Only enable decoders/weights for background generator and neuron decoders[0][int(neuron.x())] = event.getSynapseDecoderMask() weights[int(neuron.x())] = weight HICANN.set_decoder_double_row(self.h, driver, decoders) HICANN.set_weights_row(self.h, synapse_row, weights) ################### # get ADC trace # ################### self.set_denmem_quads(neuron, address=firingevent, activate_firing=firing, enable_aout=True) self.set_analog(analog, neuron) trace, v, t = self.get_trace(adc_channel, trace_length) if False: import pylab fig, ax = pylab.subplots() ax.plot(t, v) pylab.show() ## Case 1: Sometimes the membrane seems 'stuck' at 1.2V self.assertNotAlmostEqual(v.mean(), 1.2, places=1) self.assertGreater(v.std(), 0.01)