def definition(io): # Configuration data config_reg = mantle.Register(32, init=0, has_ce=True, has_reset=True) m.wire(io.config_data, config_reg.I) m.wire(io.clk, config_reg.CLK) m.wire(io.config_en, config_reg.CE) rst_inv = mantle.Invert(1) m.wire(rst_inv.I[0], io.rst) m.wire(rst_inv.O[0], config_reg.RESET) # Config mux config_mux = mantle.Mux(height=8, width=1) m.wire(config_mux.O, io.out) m.wire(config_mux.S, config_reg.O[0:3]) m.wire(io.track_0_in, config_mux.I0) m.wire(io.track_1_in, config_mux.I1) m.wire(io.track_2_in, config_mux.I2) m.wire(io.track_3_in, config_mux.I3) m.wire(io.track_0_out, config_mux.I4) m.wire(io.track_1_out, config_mux.I5) m.wire(io.track_2_out, config_mux.I6) m.wire(io.track_3_out, config_mux.I7)
def generate_output_mux(num_tracks, feedthrough_outputs, has_constant, width, mux_sel_bit_count, constant_bit_count, io, config_register): pow_2_tracks = 2**m.bitutils.clog2(num_tracks) print('# of tracks =', pow_2_tracks) output_mux = mantle.Mux(height=pow_2_tracks, width=width) m.wire(output_mux.S, config_register.O[:m.bitutils.clog2(pow_2_tracks)]) # This is only here because this is the way the switch box numbers # things. # We really should get rid of this feedthrough parameter sel_out = 0 for i in range(0, pow_2_tracks): # in_track = 'I' + str(i) if (i < num_tracks): if (feedthrough_outputs[i] == '1'): m.wire(getattr(output_mux, 'I' + str(sel_out)), getattr(io, 'in_' + str(i))) sel_out += 1 if (has_constant == 0): while (sel_out < pow_2_tracks): m.wire(getattr(output_mux, 'I' + str(sel_out)), m.uint(0, width)) sel_out += 1 else: const_val = config_register.O[mux_sel_bit_count:mux_sel_bit_count + constant_bit_count] while (sel_out < pow_2_tracks): m.wire(getattr(output_mux, 'I' + str(sel_out)), const_val) sel_out += 1 return output_mux
def create_io1out_pad(): cb = m.DefineCircuit("io1out_pad", "clk", m.In(m.Clock), "rst", m.In(m.Reset), "config_data", m.In(m.Bits(32)), "config_addr", m.In(m.Bits(32)), "tile_id", m.In(m.Bits(16)), "pin_0", m.In(m.Bit), "pin_1", m.In(m.Bit), "pin_2", m.In(m.Bit), "pin_3", m.In(m.Bit), "top_pin", m.Out(m.Bits(1))) # Configuration data config_reg = mantle.Register(32, init=0, has_ce=True, has_reset=True) addr_match = mantle.EQ(16) m.wire(addr_match.I0, cb.config_addr[0:16]) m.wire(addr_match.I1, cb.tile_id) m.wire(addr_match.O, config_reg.CE) m.wire(cb.config_data, config_reg.I) m.wire(cb.clk, config_reg.CLK) rst_inv = mantle.Invert(1) m.wire(rst_inv.I[0], cb.rst) m.wire(rst_inv.O[0], config_reg.RESET) # Config mux config_mux = mantle.Mux(height=4, width=1) m.wire(config_mux.O, cb.top_pin) m.wire(config_mux.S, config_reg.O[0:2]) m.wire(cb.pin_0, config_mux.I0[0]) m.wire(cb.pin_1, config_mux.I1[0]) m.wire(cb.pin_2, config_mux.I2[0]) m.wire(cb.pin_3, config_mux.I3[0]) m.EndDefine() return cb
def create_connect_box(): cb = m.DefineCircuit("connect_box", "operand0", m.In(m.Bits(1)), "operand1", m.In(m.Bits(1)), "result", m.Out(m.Bits(1)), "clk", m.In(m.Clock), "rst", m.In(m.Reset), "config_data", m.In(m.Bits(32)), "config_en", m.In(m.Bit)) # Configuration data config_reg = mantle.Register(32, init=0, has_ce=True, has_reset=True) m.wire(cb.config_data, config_reg.I) m.wire(cb.clk, config_reg.CLK) m.wire(cb.config_en, config_reg.CE) rst_inv = mantle.Invert(1) m.wire(rst_inv.I[0], cb.rst) m.wire(rst_inv.O[0], config_reg.RESET) # Operations in CB and_op = mantle.And(2, 1) m.wire(cb.operand0, and_op.I0) m.wire(cb.operand1, and_op.I1) or_op = mantle.Or(2, 1) m.wire(cb.operand0, or_op.I0) m.wire(cb.operand1, or_op.I1) xor_op = mantle.XOr(2, 1) m.wire(cb.operand0, xor_op.I0) m.wire(cb.operand1, xor_op.I1) not_op = mantle.Invert(1) m.wire(cb.operand0, not_op.I) # Config mux config_mux = mantle.Mux(height=4, width=1) m.wire(config_mux.O, cb.result) m.wire(config_mux.S, config_reg.O[0:2]) m.wire(and_op.O, config_mux.I0) m.wire(or_op.O, config_mux.I1) m.wire(xor_op.O, config_mux.I2) m.wire(not_op.O, config_mux.I3) return cb
def definition(io): # Configuration data config_reg = mantle.Register(32, init=0, has_ce=True, has_reset=True) m.wire(io.config_data, config_reg.I) m.wire(io.clk, config_reg.CLK) m.wire(io.config_en, config_reg.CE) rst_inv = mantle.Invert(1) m.wire(rst_inv.I[0], io.rst) m.wire(rst_inv.O[0], config_reg.RESET) # Operations in CLB and_op = mantle.And(2, 1) m.wire(io.operand0, and_op.I0) m.wire(io.operand1, and_op.I1) or_op = mantle.Or(2, 1) m.wire(io.operand0, or_op.I0) m.wire(io.operand1, or_op.I1) xor_op = mantle.XOr(2, 1) m.wire(io.operand0, xor_op.I0) m.wire(io.operand1, xor_op.I1) not_op = mantle.Invert(1) m.wire(io.operand0, not_op.I) # Config mux config_mux = mantle.Mux(height=4, width=1) m.wire(config_mux.O, io.result) m.wire(config_mux.S, config_reg.O[0:2]) m.wire(and_op.O, config_mux.I0) m.wire(or_op.O, config_mux.I1) m.wire(xor_op.O, config_mux.I2) m.wire(not_op.O, config_mux.I3)
def definition(io): # Configuration data config_reg = mantle.Register(32, init=0, has_ce=True, has_reset=True) m.wire(io.config_data, config_reg.I) m.wire(io.clk, config_reg.CLK) m.wire(io.config_en, config_reg.CE) rst_inv = mantle.Invert(1) m.wire(rst_inv.I[0], io.rst) m.wire(rst_inv.O[0], config_reg.RESET) # switch muxes config_offset = 0 for side in range(0, 4): for track in range(0, 4): switch_mux = mantle.Mux(height=4, width=1) m.wire( switch_mux.O, getattr( io, 'side_' + str(side) + '_track_' + str(track) + '_out')) m.wire(switch_mux.S, config_reg.O[config_offset:(config_offset + 2)]) config_offset += 2 for in_side in range(0, 4): if in_side == side: m.wire(getattr(switch_mux, "I" + str(in_side)), io.clb_result) else: m.wire( getattr(switch_mux, "I" + str(in_side)), getattr( io, 'side_' + str(in_side) + '_track_' + str(track) + '_in'))
def definition(io): # IF - get cycle_id, label_index_id controller = Controller() reg_1_cycle = mantle.Register(n) reg_1_control = mantle.DFF(init=1) wire(io.CLK, controller.CLK) wire(io.CLK, reg_1_cycle.CLK) wire(io.CLK, reg_1_control.CLK) reg_1_idx = controller.IDX wire(controller.CYCLE, reg_1_cycle.I) wire(1, reg_1_control.I) # RR - get weight block, image block of N bits readROM = ReadROM() wire(reg_1_idx, readROM.IDX) wire(reg_1_cycle.O, readROM.CYCLE) reg_2 = mantle.Register(N + b + n) reg_2_control = mantle.DFF() reg_2_weight = readROM.WEIGHT wire(io.CLK, reg_2.CLK) wire(io.CLK, readROM.CLK) wire(io.CLK, reg_2_control.CLK) wire(readROM.IMAGE, reg_2.I[:N]) wire(reg_1_idx, reg_2.I[N:N + b]) wire(reg_1_cycle.O, reg_2.I[N + b:]) wire(reg_1_control.O, reg_2_control.I) # EX - NXOr for multiplication, pop count and accumulate the result for activation multiplier = mantle.NXOr(height=2, width=N) bit_counter = DefineBitCounter(N)() adder = mantle.Add(n_bc_adder, cin=False, cout=False) mux_for_adder_0 = mantle.Mux(height=2, width=n_bc_adder) mux_for_adder_1 = mantle.Mux(height=2, width=n_bc_adder) reg_3_1 = mantle.Register(n_bc_adder) reg_3_2 = mantle.Register(b + n) wire(io.CLK, reg_3_1.CLK) wire(io.CLK, reg_3_2.CLK) wire(reg_2_weight, multiplier.I0) wire(reg_2.O[:N], multiplier.I1) wire(multiplier.O, bit_counter.I) wire(bits(0, n_bc_adder), mux_for_adder_0.I0) wire(bit_counter.O, mux_for_adder_0.I1[:n_bc]) if n_bc_adder > n_bc: wire(bits(0, n_bc_adder - n_bc), mux_for_adder_0.I1[n_bc:]) # only when data read is ready (i.e. control signal is high), accumulate the pop count result wire(reg_2_control.O, mux_for_adder_0.S) wire(reg_3_1.O, mux_for_adder_1.I0) wire(bits(0, n_bc_adder), mux_for_adder_1.I1) if n == 4: comparison_3 = SB_LUT4(LUT_INIT=int('0' * 15 + '1', 2)) wire( reg_2.O[N + b:], bits([ comparison_3.I0, comparison_3.I1, comparison_3.I2, comparison_3.I3 ])) else: comparison_3 = mantle.EQ(n) wire(reg_2.O[N + b:], comparison_3.I0) wire(bits(0, n), comparison_3.I1) wire(comparison_3.O, mux_for_adder_1.S) wire(mux_for_adder_0.O, adder.I0) wire(mux_for_adder_1.O, adder.I1) wire(adder.O, reg_3_1.I) wire(reg_2.O[N:], reg_3_2.I) # CF - classify the image classifier = Classifier() reg_4 = mantle.Register(n + b) reg_4_idx = classifier.O wire(io.CLK, classifier.CLK) wire(io.CLK, reg_4.CLK) wire(reg_3_1.O, classifier.I) wire(reg_3_2.O[:b], classifier.IDX) wire(reg_3_2.O, reg_4.I) # WB - wait to show the result until the end reg_5 = mantle.Register(b, has_ce=True) comparison_5_1 = mantle.EQ(b) comparison_5_2 = mantle.EQ(n) and_gate = mantle.And() wire(io.CLK, reg_5.CLK) wire(reg_4_idx, reg_5.I) wire(reg_4.O[:b], comparison_5_1.I0) wire(bits(num_classes - 1, b), comparison_5_1.I1) wire(reg_4.O[b:], comparison_5_2.I0) wire(bits(num_cycles - 1, n), comparison_5_2.I1) wire(comparison_5_1.O, and_gate.I0) wire(comparison_5_2.O, and_gate.I1) wire(and_gate.O, reg_5.CE) wire(reg_5.O, io.O) # latch the light indicating the end reg_6 = mantle.DFF() wire(io.CLK, reg_6.CLK) or_gate = mantle.Or() wire(and_gate.O, or_gate.I0) wire(reg_6.O, or_gate.I1) wire(or_gate.O, reg_6.I) wire(reg_6.O, io.D)
def definition(io): feedthrough_count = num_tracks for i in range(0, len(feedthrough_outputs)): feedthrough_count -= feedthrough_outputs[i] == '1' mux_sel_bit_count = int( math.ceil( math.log(num_tracks - feedthrough_count + has_constant, 2))) constant_bit_count = has_constant * width config_bit_count = mux_sel_bit_count + constant_bit_count config_reg_width = int(math.ceil(config_bit_count / 32.0) * 32) reset_val = num_tracks - feedthrough_count + has_constant - 1 config_reg_reset_bit_vector = [] CONFIG_DATA_WIDTH = 32 if (constant_bit_count > 0): print('constant_bit_count =', constant_bit_count) reset_bits = m.bitutils.int2seq(default_value, constant_bit_count) default_bits = m.bitutils.int2seq(reset_val, mux_sel_bit_count) print('default val bits =', reset_bits) print('reset val bits =', default_bits) # concat before assert config_reg_reset_bit_vector += default_bits config_reg_reset_bit_vector += reset_bits config_reg_reset_bit_vector = \ m.bitutils.seq2int(config_reg_reset_bit_vector) print('reset bit vec as int =', config_reg_reset_bit_vector) else: config_reg_reset_bit_vector = reset_val config_cb = mantle.Register(config_reg_width, init=config_reg_reset_bit_vector, has_ce=True, has_reset=True) config_addr_zero = mantle.EQ(8) m.wire(m.uint(0, 8), config_addr_zero.I0) m.wire(config_addr_zero.I1, io.config_addr[24:32]) config_en_set = mantle.And(2, 1) m.wire(config_en_set.I0, m.uint(1, 1)) m.wire(config_en_set.I1[0], io.config_en) config_en_set_and_addr_zero = mantle.And(2, 1) m.wire(config_en_set_and_addr_zero.I0, config_en_set.O) m.wire(config_en_set_and_addr_zero.I1[0], config_addr_zero.O) m.wire(config_en_set_and_addr_zero.O[0], config_cb.CE) config_set_mux = mantle.Mux(height=2, width=CONFIG_DATA_WIDTH) m.wire(config_set_mux.I0, config_cb.O) m.wire(config_set_mux.I1, io.config_addr) m.wire(config_set_mux.S, config_en_set_and_addr_zero.O[0]) m.wire(config_cb.RESET, io.reset) m.wire(config_cb.I, io.config_data) # Setting read data read_data_mux = mantle.Mux(height=2, width=CONFIG_DATA_WIDTH) m.wire(read_data_mux.S, equals_cmp(io.config_addr[24:32], m.uint(0, 8), 8).O) m.wire(read_data_mux.I1, config_cb.O) m.wire(read_data_mux.I0, m.uint(0, 32)) m.wire(io.read_data, read_data_mux.O) pow_2_tracks = power_log(num_tracks) print('# of tracks =', pow_2_tracks) output_mux = mantle.Mux(height=pow_2_tracks, width=width) m.wire(output_mux.S, config_cb.O[0:math.ceil(math.log(width, 2))]) # Note: Uncomment this line for select to make the unit test fail! # m.wire(output_mux.S, m.uint(0, math.ceil(math.log(width, 2)))) # This is only here because this is the way the switch box numbers # things. # We really should get rid of this feedthrough parameter sel_out = 0 for i in range(0, pow_2_tracks): # in_track = 'I' + str(i) if (i < num_tracks): if (feedthrough_outputs[i] == '1'): m.wire(getattr(output_mux, 'I' + str(sel_out)), getattr(io, 'in_' + str(i))) sel_out += 1 if (has_constant == 0): while (sel_out < pow_2_tracks): m.wire(getattr(output_mux, 'I' + str(sel_out)), m.uint(0, width)) sel_out += 1 else: const_val = config_cb.O[mux_sel_bit_count:mux_sel_bit_count + constant_bit_count] while (sel_out < pow_2_tracks): m.wire(getattr(output_mux, 'I' + str(sel_out)), const_val) sel_out += 1 # NOTE: This is a dummy! fix it later! m.wire(output_mux.O, io.out) return