diff --git a/artiq/gateware/wrpll/__init__.py b/artiq/gateware/wrpll/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/artiq/gateware/wrpll/filters.py b/artiq/gateware/wrpll/filters.py deleted file mode 100644 index 58b664754..000000000 --- a/artiq/gateware/wrpll/filters.py +++ /dev/null @@ -1,62 +0,0 @@ -helper_xn1 = 0 -helper_xn2 = 0 -helper_yn0 = 0 -helper_yn1 = 0 -helper_yn2 = 0 - -previous_helper_tag = 0 - -main_xn1 = 0 -main_xn2 = 0 -main_yn0 = 0 -main_yn1 = 0 -main_yn2 = 0 - - -def helper(helper_tag): - global helper_xn1, helper_xn2, helper_yn0, \ - helper_yn1, helper_yn2, previous_helper_tag - - helper_xn0 = helper_tag - previous_helper_tag - 32768 - - helper_yr = 4294967296 - - helper_yn2 = helper_yn1 - helper_yn1 = helper_yn0 - helper_yn0 = ( - ((284885689*((217319150*helper_xn0 >> 44) + - (-17591968725107*helper_xn1 >> 44))) >> 44) + - (-35184372088832*helper_yn1 >> 44) - - (17592186044416*helper_yn2 >> 44)) - - helper_xn2 = helper_xn1 - helper_xn1 = helper_xn0 - - previous_helper_tag = helper_tag - - helper_yn0 = min(helper_yn0, helper_yr) - helper_yn0 = max(helper_yn0, 0 - helper_yr) - - return helper_yn0 - - -def main(main_xn0): - global main_xn1, main_xn2, main_yn0, main_yn1, main_yn2 - - main_yr = 4294967296 - - main_yn2 = main_yn1 - main_yn1 = main_yn0 - main_yn0 = ( - ((133450380908*(((35184372088832*main_xn0) >> 44) + - ((17592186044417*main_xn1) >> 44))) >> 44) + - ((29455872930889*main_yn1) >> 44) - - ((12673794781453*main_yn2) >> 44)) - - main_xn2 = main_xn1 - main_xn1 = main_xn0 - - main_yn0 = min(main_yn0, main_yr) - main_yn0 = max(main_yn0, 0 - main_yr) - - return main_yn0 diff --git a/artiq/gateware/wrpll/si549.py b/artiq/gateware/wrpll/si549.py deleted file mode 100644 index 652e3f0b5..000000000 --- a/artiq/gateware/wrpll/si549.py +++ /dev/null @@ -1,265 +0,0 @@ -from migen import * -from migen.genlib.fsm import * -from migen.genlib.cdc import MultiReg, PulseSynchronizer, BlindTransfer - -from misoc.interconnect.csr import * - - -class I2CClockGen(Module): - def __init__(self, width): - self.load = Signal(width) - self.clk2x = Signal() - - cnt = Signal.like(self.load) - self.comb += [ - self.clk2x.eq(cnt == 0), - ] - self.sync += [ - If(self.clk2x, - cnt.eq(self.load), - ).Else( - cnt.eq(cnt - 1), - ) - ] - - -class I2CMasterMachine(Module): - def __init__(self, clock_width): - self.scl = Signal(reset=1) - self.sda_o = Signal(reset=1) - self.sda_i = Signal() - - self.submodules.cg = CEInserter()(I2CClockGen(clock_width)) - self.idle = Signal() - self.start = Signal() - self.stop = Signal() - self.write = Signal() - self.read = Signal() - self.ack = Signal() - self.data = Signal(8) - - ### - - busy = Signal() - bits = Signal(4) - - fsm = CEInserter()(FSM("IDLE")) - self.submodules += fsm - - fsm.act("IDLE", - If(self.start, - NextState("START0"), - ).Elif(self.stop & self.start, - NextState("RESTART0"), - ).Elif(self.stop, - NextState("STOP0"), - ).Elif(self.write, - NextValue(bits, 8), - NextState("WRITE0"), - ).Elif(self.read, - NextValue(bits, 8), - NextState("READ0"), - ) - ) - - fsm.act("START0", - NextValue(self.scl, 1), - NextState("START1")) - fsm.act("START1", - NextValue(self.sda_o, 0), - NextState("IDLE")) - - fsm.act("RESTART0", - NextValue(self.scl, 0), - NextState("RESTART1")) - fsm.act("RESTART1", - NextValue(self.sda_o, 1), - NextState("START0")) - - fsm.act("STOP0", - NextValue(self.scl, 0), - NextState("STOP1")) - fsm.act("STOP1", - NextValue(self.scl, 1), - NextValue(self.sda_o, 0), - NextState("STOP2")) - fsm.act("STOP2", - NextValue(self.sda_o, 1), - NextState("IDLE")) - - fsm.act("WRITE0", - NextValue(self.scl, 0), - If(bits == 0, - NextValue(self.sda_o, 1), - NextState("READACK0"), - ).Else( - NextValue(self.sda_o, self.data[7]), - NextState("WRITE1"), - ) - ) - fsm.act("WRITE1", - NextValue(self.scl, 1), - NextValue(self.data[1:], self.data[:-1]), - NextValue(bits, bits - 1), - NextState("WRITE0"), - ) - fsm.act("READACK0", - NextValue(self.scl, 1), - NextState("READACK1"), - ) - fsm.act("READACK1", - NextValue(self.ack, ~self.sda_i), - NextState("IDLE") - ) - - fsm.act("READ0", - NextValue(self.scl, 0), - NextState("READ1"), - ) - fsm.act("READ1", - NextValue(self.data[0], self.sda_i), - NextValue(self.scl, 0), - If(bits == 0, - NextValue(self.sda_o, ~self.ack), - NextState("WRITEACK0"), - ).Else( - NextValue(self.sda_o, 1), - NextState("READ2"), - ) - ) - fsm.act("READ2", - NextValue(self.scl, 1), - NextValue(self.data[:-1], self.data[1:]), - NextValue(bits, bits - 1), - NextState("READ1"), - ) - fsm.act("WRITEACK0", - NextValue(self.scl, 1), - NextState("IDLE"), - ) - - run = Signal() - self.comb += [ - run.eq(self.start | self.stop | self.write | self.read), - self.idle.eq(~run & fsm.ongoing("IDLE")), - self.cg.ce.eq(~self.idle), - fsm.ce.eq(run | self.cg.clk2x), - ] - - -class ADPLLProgrammer(Module): - def __init__(self): - self.i2c_divider = Signal(16) - self.i2c_address = Signal(7) - - self.adpll = Signal(24) - self.stb = Signal() - self.busy = Signal() - self.nack = Signal() - - self.scl = Signal() - self.sda_i = Signal() - self.sda_o = Signal() - - self.scl.attr.add("no_retiming") - self.sda_o.attr.add("no_retiming") - - # # # - - master = I2CMasterMachine(16) - self.submodules += master - - self.comb += [ - master.cg.load.eq(self.i2c_divider.storage), - self.scl.eq(master.scl), - master.sda_i.eq(self.sda_i), - self.sda_o.eq(master.sda_o) - ] - - -class Si549(Module, AutoCSR): - def __init__(self, pads): - self.gpio_enable = CSRStorage(reset=1) - self.gpio_in = CSRStatus(2) - self.gpio_out = CSRStorage(2) - self.gpio_oe = CSRStorage(2) - - self.i2c_divider = CSRStorage(16) - self.i2c_address = CSRStorage(7) - self.errors = CSR(2) - - # in helper clock domain - self.adpll = Signal(24) - self.adpll_stb = Signal() - - # # # - - programmer = ClockDomainsRenamer("helper")(ADPLLProgrammer()) - self.submodules += programmer - - self.i2c_divider.storage.attr.add("no_retiming") - self.i2c_address.storage.attr.add("no_retiming") - self.specials += [ - MultiReg(self.i2c_divider.storage, programmer.i2c_divider, "helper"), - MultiReg(self.i2c_address.storage, programmer.i2c_address, "helper") - ] - self.comb += [ - programmer.adpll.eq(self.adpll), - programmer.adpll_stb.eq(self.adpll_stb) - ] - - self.gpio_enable.storage.attr.add("no_retiming") - self.gpio_out.storage.attr.add("no_retiming") - self.gpio_oe.storage.attr.add("no_retiming") - - # SCL GPIO and mux - ts_scl = TSTriple(1) - self.specials += ts_scl.get_tristate(pads.scl) - - status = Signal() - self.comb += self.gpio_in.status[0].eq(status) - - self.specials += MultiReg(ts_scl.i, status) - self.comb += [ - If(self.gpio_enable.storage, - ts_scl.o.eq(self.gpio_out.storage[0]), - ts_scl.oe.eq(self.gpio_oe.storage[0]) - ).Else( - ts_scl.o.eq(programmer.scl), - ts_scl.oe.eq(1) - ) - ] - - # SDA GPIO and mux - ts_sda = TSTriple(1) - self.specials += ts_sda.get_tristate(pads.sda) - - status = Signal() - self.comb += self.gpio_in.status[1].eq(status) - - self.specials += MultiReg(ts_sda.i, status) - self.comb += [ - If(self.gpio_enable.storage, - ts_sda.o.eq(self.gpio_out.storage[1]), - ts_sda.oe.eq(self.gpio_oe.storage[1]) - ).Else( - ts_sda.o.eq(0), - ts_sda.oe.eq(~programmer.sda_o) - ) - ] - self.specials += MultiReg(ts_sda.i, programmer.sda_i, "helper") - - # Error reporting - collision_cdc = BlindTransfer("helper", "sys") - self.submodules += collision_cdc - self.comb += collision_cdc.i.eq(programmer.stb & programmer.busy) - - nack_cdc = PulseSynchronizer("helper", "sys") - self.submodules += nack_cdc - self.comb += nack_cdc.i.eq(programmer.nack) - - for n, trig in enumerate([collision_cdc.o, nack_cdc.o]): - self.sync += [ - If(self.errors.re & self.errors.r[n], self.errors.w[n].eq(0)), - If(trig, self.errors.w[n].eq(1)) - ] diff --git a/artiq/gateware/wrpll/thls.py b/artiq/gateware/wrpll/thls.py deleted file mode 100644 index 3f5aa6425..000000000 --- a/artiq/gateware/wrpll/thls.py +++ /dev/null @@ -1,636 +0,0 @@ -import inspect -import ast -from copy import copy -import operator -from functools import reduce -from collections import OrderedDict - -from migen import * -from migen.genlib.fsm import * - - -class Isn: - def __init__(self, immediate=None, inputs=None, outputs=None): - if inputs is None: - inputs = [] - if outputs is None: - outputs = [] - self.immediate = immediate - self.inputs = inputs - self.outputs = outputs - - def __repr__(self): - r = "<" - r += self.__class__.__name__ - if self.immediate is not None: - r += " (" + str(self.immediate) + ")" - for inp in self.inputs: - r += " r" + str(inp) - if self.outputs: - r += " ->" - for outp in self.outputs: - r += " r" + str(outp) - r += ">" - return r - - -class NopIsn(Isn): - opcode = 0 - -class AddIsn(Isn): - opcode = 1 - -class SubIsn(Isn): - opcode = 2 - -class MulShiftIsn(Isn): - opcode = 3 - -# opcode = 4: MulShift with alternate shift - -class MinIsn(Isn): - opcode = 5 - -class MaxIsn(Isn): - opcode = 6 - -class CopyIsn(Isn): - opcode = 7 - -class InputIsn(Isn): - opcode = 8 - -class OutputIsn(Isn): - opcode = 9 - -class EndIsn(Isn): - opcode = 10 - - -class ASTCompiler: - def __init__(self): - self.program = [] - self.data = [] - self.next_ssa_reg = -1 - self.constants = dict() - self.names = dict() - self.globals = OrderedDict() - - def get_ssa_reg(self): - r = self.next_ssa_reg - self.next_ssa_reg -= 1 - return r - - def add_global(self, name): - if name not in self.globals: - r = len(self.data) - self.data.append(0) - self.names[name] = r - self.globals[name] = r - - def input(self, name): - target = self.get_ssa_reg() - self.program.append(InputIsn(outputs=[target])) - self.names[name] = target - - def emit(self, node): - if isinstance(node, ast.BinOp): - if isinstance(node.op, ast.RShift): - if not isinstance(node.left, ast.BinOp) or not isinstance(node.left.op, ast.Mult): - raise NotImplementedError - if not isinstance(node.right, ast.Num): - raise NotImplementedError - left = self.emit(node.left.left) - right = self.emit(node.left.right) - cons = lambda **kwargs: MulShiftIsn(immediate=node.right.n, **kwargs) - else: - left = self.emit(node.left) - right = self.emit(node.right) - if isinstance(node.op, ast.Add): - cons = AddIsn - elif isinstance(node.op, ast.Sub): - cons = SubIsn - elif isinstance(node.op, ast.Mult): - cons = lambda **kwargs: MulShiftIsn(immediate=0, **kwargs) - else: - raise NotImplementedError - output = self.get_ssa_reg() - self.program.append(cons(inputs=[left, right], outputs=[output])) - return output - elif isinstance(node, ast.Call): - if not isinstance(node.func, ast.Name): - raise NotImplementedError - funcname = node.func.id - if node.keywords: - raise NotImplementedError - inputs = [self.emit(x) for x in node.args] - if funcname == "min": - cons = MinIsn - elif funcname == "max": - cons = MaxIsn - else: - raise NotImplementedError - output = self.get_ssa_reg() - self.program.append(cons(inputs=inputs, outputs=[output])) - return output - elif isinstance(node, (ast.Num, ast.UnaryOp)): - if isinstance(node, ast.UnaryOp): - if not isinstance(node.operand, ast.Num): - raise NotImplementedError - if isinstance(node.op, ast.UAdd): - transform = lambda x: x - elif isinstance(node.op, ast.USub): - transform = operator.neg - elif isinstance(node.op, ast.Invert): - transform = operator.invert - else: - raise NotImplementedError - node = node.operand - else: - transform = lambda x: x - n = transform(node.n) - if n in self.constants: - return self.constants[n] - else: - r = len(self.data) - self.data.append(n) - self.constants[n] = r - return r - elif isinstance(node, ast.Name): - return self.names[node.id] - elif isinstance(node, ast.Assign): - output = self.emit(node.value) - for target in node.targets: - assert isinstance(target, ast.Name) - self.names[target.id] = output - elif isinstance(node, ast.Return): - value = self.emit(node.value) - self.program.append(OutputIsn(inputs=[value])) - elif isinstance(node, ast.Global): - pass - else: - raise NotImplementedError - - -class Processor: - def __init__(self, data_width=32, multiplier_stages=2): - self.data_width = data_width - self.multiplier_stages = multiplier_stages - self.multiplier_shifts = [] - self.program_rom_size = None - self.data_ram_size = None - self.opcode_bits = 4 - self.reg_bits = None - - def get_instruction_latency(self, isn): - return { - AddIsn: 2, - SubIsn: 2, - MulShiftIsn: 1 + self.multiplier_stages, - MinIsn: 2, - MaxIsn: 2, - CopyIsn: 1, - InputIsn: 1 - }[isn.__class__] - - def encode_instruction(self, isn, exit): - opcode = isn.opcode - if isn.immediate is not None and not isinstance(isn, MulShiftIsn): - r0 = isn.immediate - if len(isn.inputs) >= 1: - r1 = isn.inputs[0] - else: - r1 = 0 - else: - if len(isn.inputs) >= 1: - r0 = isn.inputs[0] - else: - r0 = 0 - if len(isn.inputs) >= 2: - r1 = isn.inputs[1] - else: - r1 = 0 - r = 0 - for value, bits in ((exit, self.reg_bits), (r1, self.reg_bits), (r0, self.reg_bits), (opcode, self.opcode_bits)): - r <<= bits - r |= value - return r - - def instruction_bits(self): - return 3*self.reg_bits + self.opcode_bits - - def implement(self, program, data): - return ProcessorImpl(self, program, data) - - -class Scheduler: - def __init__(self, processor, reserved_data, program): - self.processor = processor - self.reserved_data = reserved_data - self.used_registers = set(range(self.reserved_data)) - self.exits = dict() - self.program = program - self.remaining = copy(program) - self.output = [] - - def allocate_register(self): - r = min(set(range(max(self.used_registers) + 2)) - self.used_registers) - self.used_registers.add(r) - return r - - def free_register(self, r): - assert r >= self.reserved_data - self.used_registers.discard(r) - - def find_inputs(self, cycle, isn): - mapped_inputs = [] - for inp in isn.inputs: - if inp >= 0: - mapped_inputs.append(inp) - else: - found = False - for i in range(cycle): - if i in self.exits: - r, rm = self.exits[i] - if r == inp: - mapped_inputs.append(rm) - found = True - break - if not found: - return None - return mapped_inputs - - def schedule_one(self, isn): - cycle = len(self.output) - mapped_inputs = self.find_inputs(cycle, isn) - if mapped_inputs is None: - return False - - if isn.outputs: - # check that exit slot is free - latency = self.processor.get_instruction_latency(isn) - exit = cycle + latency - if exit in self.exits: - return False - - # avoid RAW hazard with global writeback - for output in isn.outputs: - if output >= 0: - for risn in self.remaining: - for inp in risn.inputs: - if inp == output: - return False - - # Instruction can be scheduled - - self.remaining.remove(isn) - - for inp, minp in zip(isn.inputs, mapped_inputs): - can_free = inp < 0 and all(inp != rinp for risn in self.remaining for rinp in risn.inputs) - if can_free: - self.free_register(minp) - - if isn.outputs: - assert len(isn.outputs) == 1 - if isn.outputs[0] < 0: - output = self.allocate_register() - else: - output = isn.outputs[0] - self.exits[exit] = (isn.outputs[0], output) - self.output.append(isn.__class__(immediate=isn.immediate, inputs=mapped_inputs)) - - return True - - def schedule(self): - while self.remaining: - success = False - for isn in self.remaining: - if self.schedule_one(isn): - success = True - break - if not success: - self.output.append(NopIsn()) - self.output += [NopIsn()]*(max(self.exits.keys()) - len(self.output) + 1) - return self.output - - -class CompiledProgram: - def __init__(self, processor, program, exits, data, glbs): - self.processor = processor - self.program = program - self.exits = exits - self.data = data - self.globals = glbs - - def pretty_print(self): - for cycle, isn in enumerate(self.program): - l = "{:4d} {:15}".format(cycle, str(isn)) - if cycle in self.exits: - l += " -> r{}".format(self.exits[cycle]) - print(l) - - def dimension_processor(self): - self.processor.program_rom_size = len(self.program) - self.processor.data_ram_size = len(self.data) - self.processor.reg_bits = (self.processor.data_ram_size - 1).bit_length() - for isn in self.program: - if isinstance(isn, MulShiftIsn) and isn.immediate not in self.processor.multiplier_shifts: - self.processor.multiplier_shifts.append(isn.immediate) - - def encode(self): - r = [] - for i, isn in enumerate(self.program): - exit = self.exits.get(i, 0) - r.append(self.processor.encode_instruction(isn, exit)) - return r - - -def compile(processor, function): - node = ast.parse(inspect.getsource(function)) - assert isinstance(node, ast.Module) - assert len(node.body) == 1 - node = node.body[0] - assert isinstance(node, ast.FunctionDef) - assert len(node.args.args) == 1 - arg = node.args.args[0].arg - body = node.body - - astcompiler = ASTCompiler() - for node in body: - if isinstance(node, ast.Global): - for name in node.names: - astcompiler.add_global(name) - arg_r = astcompiler.input(arg) - for node in body: - astcompiler.emit(node) - if isinstance(node, ast.Return): - break - for glbl, location in astcompiler.globals.items(): - new_location = astcompiler.names[glbl] - if new_location != location: - astcompiler.program.append(CopyIsn(inputs=[new_location], outputs=[location])) - - scheduler = Scheduler(processor, len(astcompiler.data), astcompiler.program) - scheduler.schedule() - - program = copy(scheduler.output) - program.append(EndIsn()) - - max_reg = max(max(max(isn.inputs + [0]) for isn in program), max(v[1] for k, v in scheduler.exits.items())) - - return CompiledProgram( - processor=processor, - program=program, - exits={k: v[1] for k, v in scheduler.exits.items()}, - data=astcompiler.data + [0]*(max_reg - len(astcompiler.data) + 1), - glbs=astcompiler.globals) - - -class BaseUnit(Module): - def __init__(self, data_width): - self.stb_i = Signal() - self.i0 = Signal((data_width, True)) - self.i1 = Signal((data_width, True)) - self.stb_o = Signal() - self.o = Signal((data_width, True)) - - -class NopUnit(BaseUnit): - pass - - -class OpUnit(BaseUnit): - def __init__(self, op, data_width, stages): - BaseUnit.__init__(self, data_width) - - o = op(self.i0, self.i1) - stb_o = self.stb_i - for i in range(stages): - n_o = Signal(data_width) - n_stb_o = Signal() - self.sync += [ - n_o.eq(o), - n_stb_o.eq(stb_o) - ] - o = n_o - stb_o = n_stb_o - self.comb += [ - self.o.eq(o), - self.stb_o.eq(stb_o) - ] - - -class SelectUnit(BaseUnit): - def __init__(self, op, data_width): - BaseUnit.__init__(self, data_width) - - self.sync += [ - self.stb_o.eq(self.stb_i), - If(op(self.i0, self.i1), - self.o.eq(self.i0) - ).Else( - self.o.eq(self.i1) - ) - ] - - -class CopyUnit(BaseUnit): - def __init__(self, data_width): - BaseUnit.__init__(self, data_width) - - self.comb += [ - self.stb_o.eq(self.stb_i), - self.o.eq(self.i0) - ] - - -class InputUnit(BaseUnit): - def __init__(self, data_width, input_stb, input): - BaseUnit.__init__(self, data_width) - self.buffer = Signal(data_width) - - self.comb += [ - self.stb_o.eq(self.stb_i), - self.o.eq(self.buffer) - ] - - -class OutputUnit(BaseUnit): - def __init__(self, data_width, output_stb, output): - BaseUnit.__init__(self, data_width) - - self.sync += [ - output_stb.eq(self.stb_i), - output.eq(self.i0) - ] - - -class ProcessorImpl(Module): - def __init__(self, pd, program, data): - self.input_stb = Signal() - self.input = Signal((pd.data_width, True)) - - self.output_stb = Signal() - self.output = Signal((pd.data_width, True)) - - self.busy = Signal() - - # # # - - program_mem = Memory(pd.instruction_bits(), pd.program_rom_size, init=program) - data_mem0 = Memory(pd.data_width, pd.data_ram_size, init=data) - data_mem1 = Memory(pd.data_width, pd.data_ram_size, init=data) - self.specials += program_mem, data_mem0, data_mem1 - - pc = Signal(pd.instruction_bits()) - pc_next = Signal.like(pc) - pc_en = Signal() - self.sync += pc.eq(pc_next) - self.comb += [ - If(pc_en, - pc_next.eq(pc + 1) - ).Else( - pc_next.eq(0) - ) - ] - program_mem_port = program_mem.get_port() - self.specials += program_mem_port - self.comb += program_mem_port.adr.eq(pc_next) - - s = 0 - opcode = Signal(pd.opcode_bits) - self.comb += opcode.eq(program_mem_port.dat_r[s:s+pd.opcode_bits]) - s += pd.opcode_bits - r0 = Signal(pd.reg_bits) - self.comb += r0.eq(program_mem_port.dat_r[s:s+pd.reg_bits]) - s += pd.reg_bits - r1 = Signal(pd.reg_bits) - self.comb += r1.eq(program_mem_port.dat_r[s:s+pd.reg_bits]) - s += pd.reg_bits - exit = Signal(pd.reg_bits) - self.comb += exit.eq(program_mem_port.dat_r[s:s+pd.reg_bits]) - - data_read_port0 = data_mem0.get_port() - data_read_port1 = data_mem1.get_port() - self.specials += data_read_port0, data_read_port1 - self.comb += [ - data_read_port0.adr.eq(r0), - data_read_port1.adr.eq(r1) - ] - - data_write_port = data_mem0.get_port(write_capable=True) - data_write_port_dup = data_mem1.get_port(write_capable=True) - self.specials += data_write_port, data_write_port_dup - self.comb += [ - data_write_port_dup.we.eq(data_write_port.we), - data_write_port_dup.adr.eq(data_write_port.adr), - data_write_port_dup.dat_w.eq(data_write_port.dat_w), - data_write_port.adr.eq(exit) - ] - - nop = NopUnit(pd.data_width) - adder = OpUnit(operator.add, pd.data_width, 1) - subtractor = OpUnit(operator.sub, pd.data_width, 1) - if pd.multiplier_shifts: - if len(pd.multiplier_shifts) != 1: - raise NotImplementedError - multiplier = OpUnit(lambda a, b: a * b >> pd.multiplier_shifts[0], - pd.data_width, pd.multiplier_stages) - else: - multiplier = NopUnit(pd.data_width) - minu = SelectUnit(operator.lt, pd.data_width) - maxu = SelectUnit(operator.gt, pd.data_width) - copier = CopyUnit(pd.data_width) - inu = InputUnit(pd.data_width, self.input_stb, self.input) - outu = OutputUnit(pd.data_width, self.output_stb, self.output) - units = [nop, adder, subtractor, multiplier, minu, maxu, copier, inu, outu] - self.submodules += units - - for unit in units: - self.sync += unit.stb_i.eq(0) - self.comb += [ - unit.i0.eq(data_read_port0.dat_r), - unit.i1.eq(data_read_port1.dat_r), - If(unit.stb_o, - data_write_port.we.eq(1), - data_write_port.dat_w.eq(unit.o) - ) - ] - - decode_table = [ - (NopIsn.opcode, nop), - (AddIsn.opcode, adder), - (SubIsn.opcode, subtractor), - (MulShiftIsn.opcode, multiplier), - (MulShiftIsn.opcode + 1, multiplier), - (MinIsn.opcode, minu), - (MaxIsn.opcode, maxu), - (CopyIsn.opcode, copier), - (InputIsn.opcode, inu), - (OutputIsn.opcode, outu) - ] - for allocated_opcode, unit in decode_table: - self.sync += If(pc_en & (opcode == allocated_opcode), unit.stb_i.eq(1)) - - fsm = FSM() - self.submodules += fsm - fsm.act("IDLE", - pc_en.eq(0), - NextValue(inu.buffer, self.input), - If(self.input_stb, NextState("PROCESSING")) - ) - fsm.act("PROCESSING", - self.busy.eq(1), - pc_en.eq(1), - If(opcode == EndIsn.opcode, - pc_en.eq(0), - NextState("IDLE") - ) - ) - - -a = 0 -b = 0 -c = 0 - -def foo(x): - global a, b, c - c = b - b = a - a = x - return 4748*a + 259*b - 155*c - - -def simple_test(x): - global a - a = a + (x*4 >> 1) - return a - - -if __name__ == "__main__": - proc = Processor() - cp = compile(proc, simple_test) - cp.pretty_print() - cp.dimension_processor() - print(cp.encode()) - proc_impl = proc.implement(cp.encode(), cp.data) - - def send_values(values): - for value in values: - yield proc_impl.input.eq(value) - yield proc_impl.input_stb.eq(1) - yield - yield proc_impl.input.eq(0) - yield proc_impl.input_stb.eq(0) - yield - while (yield proc_impl.busy): - yield - @passive - def receive_values(callback): - while True: - while not (yield proc_impl.output_stb): - yield - callback((yield proc_impl.output)) - yield - - run_simulation(proc_impl, [send_values([42, 40, 10, 10]), receive_values(print)])