class DFF3(m.Circuit): name = make_name_dff3(array_size_2, array_size_1, width, pipe_depth, retime_status) IO = [ "data_in", m.Array(array_size_2, m.Array(array_size_1, m.In(m.Bits(width)))), "clk", m.In(m.Clock), "reset", m.In(m.Reset), "en", m.In(m.Bit), "data_out", m.Array(array_size_2, m.Array(array_size_1, m.Out(m.Bits(width)))) ] @classmethod def definition(io): dffs = m.braid(m.map_( DefineDFF2(array_size_1, width, pipe_depth, retime_status), array_size_2), joinargs=["data_in", "data_out"], forkargs=["clk", "en", "reset"]) m.wire(dffs.data_in, io.data_in) m.wire(dffs.data_out, io.data_out) m.wire(dffs.clk, io.clk) m.wire(dffs.en, io.en) m.wire(dffs.reset, io.reset)
def wrap(index_list, argtype): if len(index_list) == 1: index = index_list[0] + 1 return m.Array(index, argtype) else: index = index_list.pop(0) + 1 return m.Array(index, wrap(index_list, argtype))
def __init__(self, height, width): super().__init__() self.height = height self.width = width T = magma.Bits(self.width) # In the case that @height <= 1, we make this circuit a simple # pass-through circuit. if self.height <= 1: self.add_ports( I=magma.In(magma.Array(1, T)), O=magma.Out(T), ) self.wire(self.ports.I[0], self.ports.O) self.sel_bits = 0 return MuxCls = mantle.DefineMux(self.height, self.width) self.mux = FromMagma(MuxCls) self.sel_bits = magma.bitutils.clog2(self.height) self.add_ports( I=magma.In(magma.Array(self.height, T)), S=magma.In(magma.Bits(self.sel_bits)), O=magma.Out(T), ) for i in range(self.height): self.wire(self.ports.I[i], self.mux.ports[f"I{i}"]) mux_in = self.ports.S if self.sel_bits > 1 else self.ports.S[0] self.wire(mux_in, self.mux.ports.S) self.wire(self.mux.ports.O, self.ports.O)
def __init__(self, width, num_tracks, core_inputs): super().__init__() self.width = width self.num_tracks = num_tracks assert core_inputs == 1 self.core_inputs = core_inputs self.muxs = [MuxWrapper(self.num_tracks, self.width) \ for _ in range(self.num_tracks)] T = magma.Array(self.num_tracks, magma.Bits(self.width)) bits_per_sel = math.ceil(math.log(self.num_tracks, 2)) self.add_ports( I=magma.In(T), core_in=magma.In(magma.Array(self.core_inputs, T.T)), O=magma.Out(T), ) for i in range(self.num_tracks): self.add_config(f"sel_{i}", bits_per_sel) self.selects = [getattr(self, f"sel_{i}") \ for i in range(self.num_tracks)] for i in range(self.num_tracks): mux = self.muxs[i] for j in range(self.num_tracks): mux_in = self.I[j] if i != j else self.core_in[0] self.wire(mux_in, mux.I[j]) self.wire(self.selects[i], mux.S) self.wire(mux.O, self.O[i])
class Foo(m.Circuit): IO = [ "a", m.In(m.Bit), "b", m.In(m.Bits(8)), "c", m.In(m.Array(12, m.Bit)), "d", m.In(m.Array(16, m.Array(20, m.Bit))) ]
def SideType(num_tracks, layers): layers_dict = { f"layer{l}": magma.Array(num_tracks, magma.Bits(l)) for l in layers } T = magma.Tuple(**layers_dict) return magma.Tuple(I=magma.In(T), O=magma.Out(T))
def __init__(self, width, num_tracks, core): super().__init__() self.width = width self.num_tracks = num_tracks self.core = core self.sb = SBGenerator(self.width, self.num_tracks, len(self.core.outputs())) self.cbs = [CBGenerator(self.width, self.num_tracks) \ for _ in range(len(self.core.inputs()))] T = magma.Array(self.num_tracks, magma.Bits(self.width)) self.add_ports( I=magma.In(T), O=magma.Out(T), ) self.wire(self.I, self.sb.I) for cb in self.cbs: self.wire(self.I, cb.I) for i, core_in in enumerate(self.core.inputs()): self.wire(self.cbs[i].O, core_in) for i, core_out in enumerate(self.core.outputs()): self.wire(core_out, self.sb.core_in[i]) self.wire(self.sb.O, self.O)
class _SimpleCB(m.Circuit): name = make_name(width, num_tracks) IO = [ "I", m.In(m.Array(num_tracks, T)), "O", m.Out(T), ] IO += ConfigInterface(CONFIG_ADDR_WIDTH, CONFIG_DATA_WIDTH) IO += m.ClockInterface(has_async_reset=True) @classmethod def definition(io): config = mantle.Register(CONFIG_DATA_WIDTH, init=config_reset, has_ce=True, has_async_reset=True) config_addr_zero = m.bits(0, 8) == io.config_addr[24:32] config(io.config_data, CE=(m.bit(io.config_en) & config_addr_zero)) # If the top 8 bits of config_addr are 0, then read_data is equal # to the value of the config register, otherwise it is 0. m.wire( io.read_data, mantle.mux([m.uint(0, CONFIG_DATA_WIDTH), config.O], config_addr_zero)) # NOTE: This is not robust in the case that the mux which needs more # than 32 select bits (i.e. >= 2^32 inputs). This is unlikely to # happen, but this code is not general. out = generate_mux(io.I, config.O[:sel_bits], m.uint(0, width)) m.wire(out, io.O)
def __init__(self): super().__init__() width = 16 num_tracks = 4 num_tiles = 10 T = magma.Array(num_tracks, magma.Bits(width)) self.tiles = [] for i in range(num_tiles): if i % 2 == 0: core = PECoreGenerator(width) else: core = MemCoreGenerator(width) self.tiles.append(TileGenerator(width, num_tracks, core)) self.add_ports( I=magma.In(T), O=magma.Out(T), ) self.wire(self.I, self.tiles[0].I) self.wire(self.tiles[-1].O, self.O) for i in range(1, len(self.tiles)): t0 = self.tiles[i - 1] t1 = self.tiles[i] self.wire(t0.O, t1.I)
def __init__(self): super().__init__() width = 16 num_tracks = 4 num_tiles = 10 T = magma.Array(num_tracks, magma.Bits(width)) self.tiles = [TileGenerator(width, num_tracks) \ for _ in range(num_tiles)] self.add_ports( I=magma.In(T), O=magma.Out(T), ) # for tile in self.tiles: # self.wire(self.config_addr, tile.config_addr) # self.wire(self.config_data, tile.config_data) self.wire(self.I, self.tiles[0].I) self.wire(self.tiles[-1].O, self.O) for i in range(1, len(self.tiles)): t0 = self.tiles[i - 1] t1 = self.tiles[i] self.wire(t0.O, t1.I)
def __init__(self, width, num_tracks): super().__init__() self.width = width self.num_tracks = num_tracks core = PECoreGenerator(self.width) sb = SBGenerator(self.width, self.num_tracks, len(core.outputs())) self.add_features( core=core, sb=sb, ) for i in range(len(self.features.core.inputs())): cb = CBGenerator(self.width, self.num_tracks) self.add_feature(f"cb{i}", cb) T = magma.Array(self.num_tracks, magma.Bits(self.width)) self.add_ports( I=magma.In(T), O=magma.Out(T), ) self.wire(self.I, self.features.sb.I) for i in range(len(self.features.core.inputs())): cb = getattr(self.features, f"cb{i}") self.wire(self.I, cb.I) for i, core_in in enumerate(self.features.core.inputs()): cb = getattr(self.features, f"cb{i}") self.wire(cb.O, core_in) for i, core_out in enumerate(self.features.core.outputs()): self.wire(core_out, self.features.sb.core_in[i]) self.wire(self.features.sb.O, self.O)
def __init__(self, columns): super().__init__() assert all([c.height == columns[0].height for c in columns]) self.width = len(columns) self.height = columns[0].height self.columns = columns self.side_type = SideType(5, (1, 16)) self.add_ports( north=magma.Array(self.width, self.side_type), south=magma.Array(self.width, self.side_type), west=magma.Array(self.height, self.side_type), east=magma.Array(self.height, self.side_type), config=magma.In(ConfigurationType(32, 32)), clk=magma.In(magma.Clock), reset=magma.In(magma.AsyncReset), read_config_data=magma.Out(magma.Bits(32)), # TODO: make number of stall domains a param stall=magma.In(magma.Bits(4))) for column in self.columns: self.wire(self.ports.config, column.ports.config) self.wire(self.ports.reset, column.ports.reset) self.wire(self.ports.stall, column.ports.stall) self.wire(self.ports.west, self.columns[0].ports.west) self.wire(self.ports.east, self.columns[-1].ports.east) for i, column in enumerate(self.columns): self.wire(self.ports.north[i], column.ports.north) self.wire(self.ports.south[i], column.ports.south) for i in range(1, self.width): c0 = self.columns[i - 1] c1 = self.columns[i] for j in range(self.height): self.wire(c1.ports.west[j].O, c0.ports.east[j].I) self.wire(c0.ports.east[j].O, c1.ports.west[j].I) # OR together read_data outputs from each column # number of inputs = number of columns self.read_data_OR = FromMagma(mantle.DefineOr(len(self.columns), 32)) for i, col in enumerate(columns): self.wire(self.read_data_OR.ports[f"I{i}"], col.ports.read_config_data) # wire up column number input self.wire(col.ports.column_num, Const(magma.bits(i, 8))) self.wire(self.read_data_OR.ports.O, self.ports.read_config_data)
def __init__(self, width, height): super().__init__() self.global_controller = GlobalController(32, 32) columns = [] for i in range(width): tiles = [] for j in range(height): core = MemCore(16, 1024) if (i % 2) else PECore() tiles.append(Tile(core)) columns.append(ColumnMeso(tiles)) self.interconnect = Interconnect(columns) side_type = self.interconnect.side_type self.add_ports( north=magma.Array(width, side_type), south=magma.Array(width, side_type), west=magma.Array(height, side_type), east=magma.Array(height, side_type), jtag=JTAGType, clk_in=magma.In(magma.Clock), reset_in=magma.In(magma.AsyncReset), ) self.wire(self.ports.north, self.interconnect.ports.north) self.wire(self.ports.south, self.interconnect.ports.south) self.wire(self.ports.west, self.interconnect.ports.west) self.wire(self.ports.east, self.interconnect.ports.east) self.wire(self.ports.jtag, self.global_controller.ports.jtag) self.wire(self.ports.clk_in, self.global_controller.ports.clk_in) self.wire(self.ports.reset_in, self.global_controller.ports.reset_in) self.wire(self.global_controller.ports.config, self.interconnect.ports.config) self.wire(self.global_controller.ports.clk_out, self.interconnect.ports.clk) self.wire(self.global_controller.ports.reset_out, self.interconnect.ports.reset) self.wire(self.global_controller.ports.stall, self.interconnect.ports.stall) self.wire(self.interconnect.ports.read_config_data, self.global_controller.ports.read_data_in)
def definition(io): load = io.LOAD baud = rising(io.SCK) | falling(io.SCK) valid_counter = mantle.CounterModM(buf_size, 12, has_ce=True) m.wire(load & baud, valid_counter.CE) valid_list = [wi * (b - 1) + i * a - 1 for i in range(1, wo + 1)] # len = 32 valid = m.GND for i in valid_list: valid = valid | mantle.Decode(i, 12)(valid_counter.O) # register on input st_in = mantle.Register(width, has_ce=True) st_in(io.DATA) m.wire(load, st_in.CE) # --------------------------DOWNSCALING----------------------------- # # downscale the image from 352x288 to 32x32 Downscale = m.DeclareCircuit( 'Downscale', "I_0_0", m.In(m.Array(1, m.Array(1, m.Array(width, m.Bit)))), "WE", m.In(m.Bit), "CLK", m.In(m.Clock), "O", m.Out(m.Array(width, m.Bit)), "V", m.Out(m.Bit)) dscale = Downscale() m.wire(st_in.O, dscale.I_0_0[0][0]) m.wire(1, dscale.WE) m.wire(load, dscale.CLK) add16 = mantle.Add(width) # needed for Add16 definition # threshold the downscale output px_bit = mantle.ULE(16)(dscale.O, m.uint(THRESH, 16)) & valid # ---------------------------UART OUTPUT----------------------------- # m.wire(px_bit, io.O) m.wire(valid, io.VALID)
def __init__(self, num_tracks, width): super().__init__() if num_tracks <= 1: raise ValueError("num_tracks must be > 1") self.num_tracks = num_tracks self.width = width sel_bits = magma.bitutils.clog2(self.num_tracks) self.mux = MuxWrapper(self.num_tracks, self.width) T = magma.Bits(self.width) self.add_ports( I=magma.In(magma.Array(self.num_tracks, T)), O=magma.Out(T), clk=magma.In(magma.Clock), reset=magma.In(magma.AsyncReset), config=magma.In(ConfigurationType(8, 32)), read_config_data=magma.Out(magma.Bits(32)), ) self.add_configs(S=sel_bits) # read_config_data output num_config_reg = len(self.registers) if (num_config_reg > 1): self.read_config_data_mux = MuxWrapper(num_config_reg, 32) self.wire(self.ports.config.config_addr, self.read_config_data_mux.ports.S) self.wire(self.read_config_data_mux.ports.O, self.ports.read_config_data) for idx, reg in enumerate(self.registers.values()): self.wire(reg.ports.O, self.read_config_data_mux.ports.I[idx]) # Wire up config register resets self.wire(reg.ports.reset, self.ports.reset) # If we only have 1 config register, we don't need a mux # Wire sole config register directly to read_config_data_output else: reg = list(self.registers.values())[0] zext = ZextWrapper(reg.width, 32) self.wire(reg.ports.O, zext.ports.I) zext_out = zext.ports.O self.wire(zext_out, self.ports.read_config_data) self.wire(self.ports.I, self.mux.ports.I) self.wire(self.registers.S.ports.O, self.mux.ports.S) self.wire(self.mux.ports.O, self.ports.O) for idx, reg in enumerate(self.registers.values()): reg.set_addr(idx) reg.set_addr_width(8) reg.set_data_width(32) self.wire(self.ports.config.config_addr, reg.ports.config_addr) self.wire(self.ports.config.config_data, reg.ports.config_data) # Connect config_en for each config reg self.wire(reg.ports.config_en, self.ports.config.write[0])
def __init__(self, num_inputs, width, sel_bits, default): super().__init__() self.num_inputs = num_inputs self.width = width self.sel_bits = sel_bits self.default = default if 2**self.sel_bits <= self.num_inputs: raise ValueError(f"(2 ^ sel_bits) must be > num_inputs " f"(sel_bits={self.sel_bits}, " f"num_inputs={self.num_inputs})") self.data_mux = MuxWrapper(self.num_inputs, self.width) self.default_mux = MuxWrapper(2, self.width) lt = mantle.DefineULT(self.sel_bits) and_gate = mantle.DefineAnd(2) self.lt = FromMagma(lt) self.and_gate = FromMagma(and_gate) T = magma.Bits(self.width) self.add_ports( I=magma.In(magma.Array(self.num_inputs, T)), S=magma.In(magma.Bits(self.sel_bits)), EN=magma.In(magma.Bits(1)), O=magma.Out(T), ) # Wire data inputs to data mux. for i in range(self.num_inputs): self.wire(self.ports.I[i], self.data_mux.ports.I[i]) # Wire select input to select input of data_mux. Note that we only wire # the first clog2(num_inputs) bits of the select input. self.wire(self.ports.S[:self.data_mux.sel_bits], self.data_mux.ports.S) # Wire default value to first input of default mux, and output of # data_mux to second input of default mux. default_mux_inputs = [ Const(magma.bits(self.default, self.width)), self.data_mux.ports.O, ] for i, mux_in in enumerate(default_mux_inputs): self.wire(mux_in, self.default_mux.ports.I[i]) # Generate select logic for default mux: # sel = (S < num_inputs) & EN self.wire(self.ports.S, self.lt.ports.I0) self.wire(Const(magma.bits(self.num_inputs, self.sel_bits)), self.lt.ports.I1) self.wire(self.lt.ports.O, self.and_gate.ports.I0) self.wire(self.ports.EN[0], self.and_gate.ports.I1) self.wire(self.and_gate.ports.O, self.default_mux.ports.S[0]) self.wire(self.default_mux.ports.O, self.ports.O)
def test_binary_primitive(binary_primitive, width): primitive_name, primitive_op, signed = binary_primitive prim = m.DeclareCircuit(f"primitive_name", "in0", m.In(m.Array(width, m.Bit)), "in1", m.In(m.Array(width, m.Bit)), "out", m.Out(m.Array(width, m.Bit)), coreir_lib="coreir", coreir_name=primitive_name, coreir_genargs={"width": width}) circ = m.DefineCircuit(f"DesignTop", "I0", m.In(m.Array(width, m.Bit)), "I1", m.In(m.Array(width, m.Bit)), "O", m.Out(m.Array(width, m.Bit))) inst = prim() m.wire(circ.I0, inst.in0) m.wire(circ.I1, inst.in1) m.wire(circ.O, inst.out) m.EndDefine() m.compile(f"build/{primitive_name}", circ, output="coreir") dir_path = os.path.dirname(os.path.realpath(__file__)) result = delegator.run( f"CGRAMapper/bin/cgra-mapper build/{primitive_name}.json build/{primitive_name}_mapped.json", cwd=dir_path) assert not result.return_code, result.out + "\n" + result.err result = delegator.run(f"./CGRAGenerator/bin/generate.csh") assert not result.return_code, result.out + "\n" + result.err result = delegator.run( f"CGRAGenerator/bitstream/bsbuilder/serpent.csh build/{primitive_name}_mapped.json -cgra_info CGRAGenerator/hardware/generator_z/top/cgra_info.txt -o build/{primitive_name}_mapped_annotated" ) assert not result.return_code, result.out + "\n" + result.err
def __init__(self, tiles): super().__init__() self.tiles = tiles self.height = len(tiles) self.add_ports( north=SideType(5, (1, 16)), south=SideType(5, (1, 16)), west=magma.Array(self.height, SideType(5, (1, 16))), east=magma.Array(self.height, SideType(5, (1, 16))), config=magma.In(ConfigurationType(32, 32)), clk=magma.In(magma.Clock), reset=magma.In(magma.AsyncReset), read_config_data=magma.Out(magma.Bits(32)), column_num=magma.In(magma.Bits(8)), # TODO (alexcarsello): make number of stall domains a param stall=magma.In(magma.Bits(4))) self.wire(self.ports.north, self.tiles[0].ports.north) self.wire(self.ports.south, self.tiles[-1].ports.south) for i, tile in enumerate(self.tiles): self.wire(self.ports.west[i], tile.ports.west) self.wire(self.ports.east[i], tile.ports.east) # Wire upper 8 bits of tile ID to row number self.wire(tile.ports.tile_id[8:16], Const(magma.bits(i, 8))) # Wire lower 8 bits of tile ID to col number self.wire(tile.ports.tile_id[0:8], self.ports.column_num) for i in range(1, self.height): t0 = self.tiles[i - 1] t1 = self.tiles[i] self.wire(t1.ports.north.O, t0.ports.south.I) self.wire(t0.ports.south.O, t1.ports.north.I) # Call abstract functions # distribute global inputs to all tiles in column self.wire_global_signals() # OR-combine each tile's read_data to form column read_data self.combine_read_data_outputs()
def DefineTester(cgra_file, collateral_file, wrapped_name): cgra_def = m.DeclareFromVerilogFile(cgra_file)[0] with open(collateral_file, 'r') as f: io_d = json.load(f) ios = _flatten( chain(_CGRA_SIGNAL_PORTS, ((mod, m.Array(int(c['width']), _s2b(c['mode']))) for mod, c in io_d.items()))) class Tester(m.Circuit): name = wrapped_name IO = ios @classmethod def definition(io): cgra = cgra_def() for port in io.interface: if port in io_d: #port is a pin direct = io_d[port]['mode'] for bit, pad in io_d[port]['bits'].items(): try: #pad + '_' + direct is the 'de-tristated' name m.wire(cgra.interface[pad + '_' + direct], io.interface[port][int(bit)]) except KeyError as e: Print( 'Looks like their is some sort of inconsistency between the cgra_info (or at least the collateral) and top.v' ) raise e else: #port is a control signal try: m.wire(cgra.interface[port], io.interface[port]) except KeyError as e: Print( 'Looks like _CGRA_SIGNAL_PORTS is no longer correct' ) raise e for port in cgra.interface: if cgra.interface[port].value() is None and isinstance( cgra.interface[port], m.BitIn): m.wire(cgra.interface[port], m.GND) return Tester
def __init__(self, width, num_tracks): super().__init__() self.width = width self.num_tracks = num_tracks is_power_of_two = lambda x: x != 0 and ((x & (x - 1)) == 0) assert is_power_of_two(self.num_tracks) self.mux = MuxWrapper(self.num_tracks, self.width) T = magma.Bits(self.width) sel_bits = magma.bitutils.clog2(self.num_tracks) self.add_ports( I=magma.In(magma.Array(self.num_tracks, T)), O=magma.Out(T), ) self.add_configs(sel=sel_bits, ) self.wire(self.I, self.mux.I) self.wire(self.sel, self.mux.S) self.wire(self.mux.O, self.O)
def __init__(self, height, width): super().__init__() self.height = height self.width = width MuxCls = mantle.DefineMux(self.height, self.width) self.mux = FromMagma(MuxCls) T = magma.Bits(width) sel_bits = magma.bitutils.clog2(self.height) self.add_ports( I=magma.In(magma.Array(self.height, T)), S=magma.In(magma.Bits(sel_bits)), O=magma.Out(T), ) for i in range(self.height): self.wire(self.I[i], getattr(self.mux, f"I{i}")) self.wire(self.S, self.mux.S) self.wire(self.mux.O, self.O)
def __init__(self, width, num_tracks): super().__init__() self.width = width self.num_tracks = num_tracks is_power_of_two = lambda x: x != 0 and ((x & (x - 1)) == 0) assert is_power_of_two(self.num_tracks) self.mux = FromMagma(mantle.DefineMux(self.num_tracks, self.width)) T = magma.Bits(self.width) sel_bits = math.ceil(math.log(self.num_tracks, 2)) self.add_ports( I=magma.In(magma.Array(self.num_tracks, T)), O=magma.Out(T), ) self.add_configs(sel=sel_bits, ) for i in range(self.num_tracks): self.wire(self.I[i], getattr(self.mux, f"I{i}")) self.wire(self.sel, self.mux.S) self.wire(self.mux.O, self.O)
import magma as m from magma.bitutils import int2seq import mantle from rom import ROM8, ROM16 from loam.boards.icestick import IceStick from uart import UART a = 2 b = 2 width = 16 TIN = m.Array(width, m.BitIn) TOUT = m.Array(width, m.Out(m.Bit)) icestick = IceStick() icestick.Clock.on() for i in range(3): icestick.J3[i].output().on() main = icestick.main() # baud for uart output clock = mantle.CounterModM(103, 8) baud = clock.COUT bit_counter = mantle.Counter(5, has_ce=True) m.wire(baud, bit_counter.CE) load = mantle.Decode(0, 5)(bit_counter.O) # # "test" data
def definition(io): load = io.LOAD baud = rising(io.SCK) | falling(io.SCK) valid_counter = mantle.CounterModM(buf_size, 12, has_ce=True) m.wire(load & baud, valid_counter.CE) valid_list = [wi * (b - 1) + i * a - 1 for i in range(1, wo + 1)] # len = 32 valid = m.GND for i in valid_list: valid = valid | mantle.Decode(i, 12)(valid_counter.O) # register on input st_in = mantle.Register(width, has_ce=True) st_in(io.DATA) m.wire(load, st_in.CE) # --------------------------DOWNSCALING----------------------------- # # downscale the image from 352x288 to 32x32 Downscale = m.DeclareCircuit( 'Downscale', "I_0_0", m.In(m.Array(1, m.Array(1, m.Array(width, m.Bit)))), "WE", m.In(m.Bit), "CLK", m.In(m.Clock), "O", m.Out(m.Array(width, m.Bit)), "V", m.Out(m.Bit)) dscale = Downscale() m.wire(st_in.O, dscale.I_0_0[0][0]) m.wire(1, dscale.WE) m.wire(load, dscale.CLK) add16 = mantle.Add(width) # needed for Add16 definition # --------------------------FILL IMG RAM--------------------------- # # each valid output of dscale represents an entry of 32x32 binary image # accumulate each group of 32 entries into a 32-bit value representing a row col = mantle.CounterModM(32, 6, has_ce=True) col_ce = rising(valid) m.wire(col_ce, col.CE) # shift each bit in one at a time until we get an entire row px_bit = mantle.ULE(16)(dscale.O, m.uint(THRESH, 16)) & valid row_reg = mantle.SIPO(32, has_ce=True) row_reg(px_bit) m.wire(col_ce, row_reg.CE) # reverse the row bits since the image is flipped row = reverse(row_reg.O) rowaddr = mantle.Counter(6, has_ce=True) img_full = mantle.SRFF(has_ce=True) img_full(mantle.EQ(6)(rowaddr.O, m.bits(32, 6)), 0) m.wire(falling(col.COUT), img_full.CE) row_ce = rising(col.COUT) & ~img_full.O m.wire(row_ce, rowaddr.CE) waddr = rowaddr.O[:5] rdy = col.COUT & ~img_full.O pulse_count = mantle.Counter(2, has_ce=True) we = mantle.UGE(2)(pulse_count.O, m.uint(1, 2)) pulse_count(CE=(we|rdy)) # ---------------------------UART OUTPUT----------------------------- # row_load = row_ce row_baud = mantle.FF()(baud) uart_row = UART(32) uart_row(CLK=io.CLK, BAUD=row_baud, DATA=row, LOAD=row_load) uart_addr = UART(5) uart_addr(CLK=io.CLK, BAUD=row_baud, DATA=waddr, LOAD=row_load) m.wire(waddr, io.WADDR) m.wire(img_full, io.DONE) #img_full m.wire(uart_row, io.UART) #uart_st m.wire(row, io.O) m.wire(we, io.VALID) m.wire(valid, io.T0) m.wire(uart_addr, io.T1)
for i in valid_list: valid = valid | mantle.Decode(i, 13)(valid_counter.O) m.wire(load & baud, printf.CE) px_val = rom.O # register on input st_in = mantle.Register(16, has_ce=True) st_in(px_val) m.wire(load, st_in.CE) # ---------------------------STENCILING----------------------------- # Downscale = m.DeclareCircuit('Downscale', "I_0_0", m.In(m.Array(1, m.Array(1, m.Array(16, m.Bit)))), "WE", m.In(m.Bit), "CLK", m.In(m.Clock), "O", m.Out(m.Array(16, m.Bit)), "V", m.Out(m.Bit)) dscale = Downscale() m.wire(st_in.O, dscale.I_0_0[0][0]) m.wire(1, dscale.WE) m.wire(load, dscale.CLK) add16 = mantle.Add(16) # needed for Add16 definition # ---------------------------UART OUTPUT----------------------------- # uart_px = UART(16) uart_px(CLK=main.CLKIN, BAUD=baud, DATA=px_val, LOAD=load)
def definition(io): load = io.LOAD baud = io.BAUD valid_counter = mantle.CounterModM(buf_size, 13, has_ce=True) m.wire(load & baud, valid_counter.CE) valid_list = [wi * (b - 1) + i * a - 1 for i in range(1, wo + 1)] valid = m.GND for i in valid_list: valid = valid | mantle.Decode(i, 13)(valid_counter.O) # register on input st_in = mantle.Register(16, has_ce=True) st_in(io.DATA) m.wire(load, st_in.CE) # --------------------------DOWNSCALING----------------------------- # # downscale the image from 320x240 to 16x16 Downscale = m.DeclareCircuit( 'Downscale', "I_0_0", m.In(m.Array(1, m.Array(1, m.Array(16, m.Bit)))), "WE", m.In(m.Bit), "CLK", m.In(m.Clock), "O", m.Out(m.Array(16, m.Bit)), "V", m.Out(m.Bit)) dscale = Downscale() m.wire(st_in.O, dscale.I_0_0[0][0]) m.wire(1, dscale.WE) m.wire(load, dscale.CLK) add16 = mantle.Add(16) # needed for Add16 definition # --------------------------FILL IMG RAM--------------------------- # # each valid output of dscale represents an entry of 16x16 binary image # accumulate each group of 16 entries into a 16-bit value representing # a row of the image col = mantle.Counter(4, has_ce=True) row_full = mantle.SRFF(has_ce=True) row_full(mantle.EQ(4)(col.O, m.bits(15, 4)), 0) m.wire(falling(dscale.V), row_full.CE) col_ce = rising(dscale.V) & ~row_full.O m.wire(col_ce, col.CE) row = mantle.Counter(4, has_ce=True) img_full = mantle.SRFF(has_ce=True) img_full(mantle.EQ(4)(row.O, m.bits(15, 4)), 0) m.wire(falling(col.COUT), img_full.CE) row_ce = rising(col.COUT) & ~img_full.O m.wire(row_ce, row.CE) # ---------------------------UART OUTPUT----------------------------- # uart_st = UART(16) uart_st(CLK=io.CLK, BAUD=baud, DATA=dscale.O, LOAD=load) m.wire(row.O, io.ROW) m.wire(img_full.O, io.DONE) m.wire(uart_st.O, io.UART)
for i in valid_list: valid = valid | mantle.Decode(i, 3)(valid_counter.O) m.wire(load & baud, printf.CE) px_val = rom.O st_in = mantle.Register(16, has_ce=True) st_in(px_val) m.wire(load, st_in.CE) # ---------------------------STENCILING----------------------------- # STEN = m.DeclareCircuit('STEN', "I_0_0", m.In(m.Array(1, m.Array(1, m.Array(16, m.Bit)))), "O", m.Out(m.Array(16, m.Bit)), "WE", m.In(m.Bit), "V", m.Out(m.Bit), "CLK", m.In(m.Clock), "CLKOut", m.Out(m.Clock), "L00", m.Out(m.Array(16, m.Bit)), "L01", m.Out(m.Array(16, m.Bit)), "L10", m.Out(m.Array(16, m.Bit)), "L11", m.Out(m.Array(16, m.Bit))) stencil = STEN() m.wire(st_in.O, stencil.I_0_0[0][0]) m.wire(1, stencil.WE) m.wire(load, stencil.CLK) add16 = mantle.CounterModM(1, 16) # needed for Add16 definition
# downscale factor (a x b) a = 11 b = 9 samples = 16 # image dimensions (height and width) im_w = 320 im_h = 240 c = coreir.Context() cirb = CoreIRBackend(c) # 8-bit values but extend to 16-bit to avoid carryover in addition width = 16 TIN = m.Array(width, m.BitIn) TOUT = m.Array(width, m.Out(m.Bit)) # Line Buffer interface inType = m.Array(1, m.Array(1, TIN)) # one pixel in per clock outType = m.Array(b, m.Array(a, TOUT)) # downscale window imgType = m.Array(im_h, m.Array(im_w, TIN)) # image dimensions # Reduce interface inType2 = m.In(m.Array(a * b, TIN)) outType2 = TOUT # Top level module: line buffer input, reduce output args = ['I', inType, 'O', outType2, 'WE', m.BitIn, 'V', m.Out(m.Bit)] + \ m.ClockInterface(False, False) dscale = m.DefineCircuit('Downscale', *args)
class Scoreboard(m.Circuit): NUM_REQS = 4 name = "Scoreboard" assert not ARBITER or NUM_REQS is not None, "If using arbiter, need to supply NUM_REQS" assert not ARBITER or QWID is not None, "If using arbiter, need to supply QWID" if ARBITER: IO = [ "push", m.In(m.Bits(NUM_REQS)), "start", m.In(m.Bit), "rst", m.In(m.Reset), # include blk sometime in the future "data_in", m.In(m.Array(N=NUM_REQS, T=m.Bits(DATAWID))), "input_quantums", m.In(m.Array(N=NUM_REQS, T=m.UInt(QWID))), "data_out_vld", m.Out(m.Bit) ] + m.ClockInterface() else: IO = [ "push", m.In(m.Bit), "pop", m.In(m.Bit), "start", m.In(m.Bit), "rst", m.In(m.Reset), "data_in", m.In(m.Bits(DATAWID)), "data_out_vld", m.Out(m.Bit) ] + m.ClockInterface() if NUM_REQS is None: NUM_REQS = 1 @classmethod def definition(io): en = DefineRegister(1, init=0, has_ce=False, has_reset=True, _type=m.Bits)(name="en") # wire clock m.wireclock(en, io) # wire reset m.wire(io.rst, en.RESET) # enable only goes high once, then stays high m.wire(en.O | m.bits(io.start), en.I) mpt = DefineMagicPacketTracker(DEPTH)() # wire up magic packet tracker m.wire(en.O, m.bits(mpt.captured)) m.wire(io.rst, mpt.rst) m.wireclock(io, mpt) if not ARBITER: m.wire(io.push, mpt.push) m.wire(io.pop, mpt.pop) fifo = DefineFIFO(DATAWID, DEPTH)() # wire up fifo m.wire(io.push, fifo.push) m.wire(io.pop, fifo.pop) m.wire(io.rst, fifo.rst) m.wire(io.data_in, fifo.data_in) m.wireclock(io, fifo) else: m.wire(io.push[0], mpt.push) fifos = list() for i in range(NUM_REQS): f = DefineFIFO(DATAWID, DEPTH)(name="fifo_{}".format(i)) fifos.append(f) m.wire(io.push[i], f.push) m.wire(io.rst, f.rst) m.wire(io.data_in[i], f.data_in) m.wireclock(io, f) # Need to wire things up if ARBITER: arb = DefineDWRR(NUM_REQS, QWID, DATAWID)(name="arb") m.wire(io.rst, arb.rst) m.wire(io.input_quantums, arb.quantums) for i in range(NUM_REQS): m.wire(~fifos[i].empty, arb.reqs[i]) m.wire(arb.gnt[i], fifos[i].pop) m.wire(arb.gnt[0], mpt.pop) # vld out # TODO handle missing magic packet -- need to reset everything. Or keep as an assumption/restriction m.wire( m.bit(en.O) & eq(m.uint(mpt.next_cnt), m.uint(0, (DEPTH - 1).bit_length())) & eq(m.uint(mpt.cnt), m.uint(1, (DEPTH - 1).bit_length())), io.data_out_vld)
from coreir.context import * from magma.simulator.coreir_simulator import CoreIRSimulator import coreir from magma.scope import Scope from mantle.coreir import DefineCoreirConst from mantle import CounterModM, Decode, SIPO from magma.frontend.coreir_ import GetCoreIRModule from mantle.coreir.arith import * from mantle.primitives import DeclareAdd c = coreir.Context() cirb = CoreIRBackend(c) scope = Scope() TIN = m.Array(16, m.BitIn) TOUT = m.Array(16, m.Out(Bit)) # Line Buffer interface inType = m.Array(1, m.Array(1, TIN)) outType = m.Array(2, m.Array(2, TOUT)) imgType = m.Array(4, m.Array(4, TIN)) # Reduce interface inType2 = m.In(m.Array(4, TIN)) outType2 = m.Out(m.Array(16, Bit)) # Test circuit has line buffer's input and reduce's output args = ['I', inType, 'O', outType2, 'WE', BitIn, 'V', m.Out(m.Bit), 'L00', TOUT, 'L01', TOUT, 'L10', TOUT, 'L11', TOUT] + \ m.ClockInterface(False, False)