def DefineMapSequential(numInputs: int, op: DefineCircuitKind) -> DefineCircuitKind: """ Map an operation over numInputs inputs over numInputs cycles. Note: the entire inputs must be delivered on the first cycle. There is no point in implementing the streaming version of this operation as that is just the module op. Aetherling Type: {1, T[numInputs]} -> {1, S[numInputs]} This returns a circuit definition. :param cirb: The CoreIR backend currently be used :param numInputs: The number of input elements :param op: The operator (the coreir module) to map over the elements. It should s.t. Op : T -> S :return: A module with all the ports of op, except that they will be converted to arrays of original type, with each array of length numInputs. For example, if op has one input port I and one output O, the ports will be: I : In(Array[numInputs, T] O : Out(Array[numInputs, S]) """ cirb = GetCoreIRBackend() if op.is_instance and op.defn.instances.__contains__(op): op.defn.instances.remove(op) name = "MapSequential_n{}_op{}".format(str(numInputs), cleanName(str(op))) definitionToReturn = DefineCircuitFromGeneratorWrapper( cirb, "aetherlinglib", "mapSequential", name, ["commonlib", "mantle", "coreir", "global"], { "numInputs": numInputs, "operator": GetCoreIRModule(cirb, op) }) return definitionToReturn
def DefineMapParallel(numInputs: int, op: DefineCircuitKind) -> DefineCircuitKind: """ Map an operation over numInputs inputs in one clock cycle Aetherling Type: {1, T[numInputs]} -> {1, S[numInputs]} This returns a circuit definition. :param cirb: The CoreIR backend currently be used :param numInputs: The number of input elements :param op: The operator (the magma circuit) to map over the elements. It should have type T -> S :return: A module with all the ports of op, except that they will be converted to arrays of original type, with each array of length numInputs. For example, if op has one input port I and one output O, the ports will be: I : In(Array[numInputs, T]) O : Out(Array[numInputs, S]) """ cirb = GetCoreIRBackend() if hasattr(op, 'is_instance' ) and op.is_instance and op.defn.instances.__contains__(op): op.defn.instances.remove(op) name = "MapParallel_n{}_op{}".format(str(numInputs), cleanName(str(op))) definitionToReturn = DefineCircuitFromGeneratorWrapper( cirb, "aetherlinglib", "mapParallel", name, ["commonlib", "mantle", "coreir", "global"], { "numInputs": numInputs, "operator": GetCoreIRModule(cirb, op) }) return definitionToReturn
def ReduceParallel(cirb: CoreIRBackend, numInputs: int, op: Circuit) -> Circuit: """ Reduce multiple numInputs into one in one clock cycle. This uses a reduction tree but can handle numInputs that aren't powers of 2. It does this using the identity element to fill in inputs to the tree that aren't used. Aetherling Type: ({1, T[numInputs]} -> {1, T}, 1) :param cirb: The CoreIR backend currently be used :param numInputs: The number of input elements :param op: The operator (the magma circuit) to map over the elements. It should have type T -> T -> T, with input ports in0 and in1. :return: A module with ports: I: In({ data: Array(numInputs, T), identity: T }) out: Out(T) """ if op.is_instance and op.defn.instances.__contains__(op): op.defn.instances.remove(op) name = "ReduceParallel_n{}_op{}".format(str(numInputs), cleanName(str(type(op)))) moduleToReturn = CircuitInstanceFromGeneratorWrapper( cirb, "aetherlinglib", "reduceParallel", name, ["commonlib", "mantle", "coreir", "global"], { "numInputs": numInputs, "operator": GetCoreIRModule(cirb, op) }) return moduleToReturn
def ReduceSequential(cirb: CoreIRBackend, numInputs: int, op: Circuit) -> Circuit: """ Reduce multiple numInputs into one in numInputs clock cycles. Aetherling Type: ({numInputs, T} -> {1, T}, numInputs) :param cirb: The CoreIR backend currently be used :param numInputs: The number of input elements :param op: The operator (the magma circuit) to map over the elements. It should have type T -> T -> T, with input ports in0 and in1. :return: A module with ports: I: In(T) out: Out(T) valid: Out(Bit) """ if op.is_instance and op.defn.instances.__contains__(op): op.defn.instances.remove(op) name = "ReduceSequentail_n{}_op{}".format(str(numInputs), cleanName(str(type(op)))) moduleToReturn = CircuitInstanceFromGeneratorWrapper( cirb, "aetherlinglib", "reduceSequential", name, ["commonlib", "mantle", "coreir", "global"], { "numInputs": numInputs, "operator": GetCoreIRModule(cirb, op) }) return moduleToReturn
def test_nested_clocks(): c = coreir.Context() cirb = CoreIRBackend(c) args = ['clocks', In(Array[2, Clock])] inner_test_circuit = DefineCircuit('inner_test_nested_clocks', *args) EndCircuit() test_circuit = DefineCircuit('test_nested_clocks', *args) inner_test_circuit() EndCircuit() GetCoreIRModule(cirb, test_circuit)
m.ClockInterface(False, False) dscale = m.DefineCircuit('Downscale', *args) # Line buffer declaration lb = Linebuffer(cirb, inType, outType, imgType, True) m.wire(lb.I, dscale.I) m.wire(lb.wen, dscale.WE) # Reduce declaration red = ReduceParallel(cirb, samples, renameCircuitForReduce(DeclareAdd(width))) # additive identity coreirConst = DefineCoreirConst(width, 0)() # select 16 samples to keep k = 0 for i in [0, 3, 5, 8]: for j in [0, 3, 7, 10]: m.wire(red.I.data[k], lb.out[i][j]) k += 1 m.wire(red.I.identity, coreirConst.O) m.wire(dscale.O, red.out) m.wire(dscale.V, lb.valid) m.EndCircuit() module = GetCoreIRModule(cirb, dscale) module.save_to_file("downscale_32.json") print("done")
testcircuit = m.DefineCircuit('STEN', *args) # Line buffer declaration lb = Linebuffer(cirb, inType, outType, imgType, True) m.wire(lb.I, testcircuit.I) m.wire(lb.wen, testcircuit.WE) # # Reduce declaration reducePar = ReduceParallel(cirb, 4, renameCircuitForReduce(DeclareAdd(16))) coreirConst = DefineCoreirConst(16, 0)() m.wire(reducePar.I.data[0], lb.out[0][0]) m.wire(reducePar.I.data[1], lb.out[0][1]) m.wire(reducePar.I.data[2], lb.out[1][0]) m.wire(reducePar.I.data[3], lb.out[1][1]) m.wire(reducePar.I.identity, coreirConst.O) m.wire(testcircuit.O, reducePar.out) m.wire(testcircuit.V, lb.valid) m.wire(lb.out[0][0], testcircuit.L00) m.wire(lb.out[0][1], testcircuit.L01) m.wire(lb.out[1][0], testcircuit.L10) m.wire(lb.out[1][1], testcircuit.L11) m.EndCircuit() module = GetCoreIRModule(cirb, testcircuit) module.save_to_file("linebuffer.json") print("done")
args = ['I', inType, 'O', outType2, 'WE', m.BitIn, 'V', m.Out(m.Bit)] + \ m.ClockInterface(False, False) top = m.DefineCircuit('Downscale', *args) # Line buffer declaration lb = Linebuffer(cirb, inType, outType, imgType, True) m.wire(lb.I, top.I) m.wire(lb.wen, top.WE) # Reduce declaration red = ReduceParallel(cirb, a * b, renameCircuitForReduce(DeclareAdd(width))) # additive identity coreirConst = DefineCoreirConst(width, 0)() # flatten linebuffer output and wire to reduce parallel input for i in range(b): for j in range(a): k = a * i + j m.wire(red.I.data[k], lb.out[i][j]) m.wire(red.I.identity, coreirConst.out) m.wire(top.O, red.out) m.wire(top.V, lb.valid) m.EndCircuit() module = GetCoreIRModule(cirb, top) module.save_to_file("downscale.json") print("done")
# test circuit has line buffer's input and reduce's output args = ['I', inType, 'O', outType, 'WE', m.BitIn, 'V', m.Out(m.Bit)] + \ m.ClockInterface(False, False) reduceHybrid = m.DefineCircuit('ReduceHybrid', *args) # reduce Parallel reducePar = ReduceParallel(cirb, a, renameCircuitForReduce(DeclareAdd(width))) coreirConst = DefineCoreirConst(width, 0)() # reduce sequential reduceSeq = ReduceSequential(cirb, b, renameCircuitForReduce(DefineAdd(width))) # top level input fed to reduce parallel input m.wire(reduceHybrid.I, reducePar.I.data) m.wire(reducePar.I.identity, coreirConst.out) # reduce parallel output fed to reduce sequential input m.wire(reducePar.out, reduceSeq.I) # output of reduce sequential fed to top level output m.wire(reduceSeq.out, reduceHybrid.O) m.wire(reduceSeq.valid, reduceHybrid.V) m.EndCircuit() module = GetCoreIRModule(cirb, reduceHybrid) module.save_to_file("reducehybrid.json") print("done")
def save_CoreIR_json(cirb, module, file): mod = GetCoreIRModule(cirb, module) mod.save_to_file(file)
args = ['I0', in_LB, 'I1', in_W, 'WE', m.BitIn, 'O', out_MAC, 'V', m.Out(m.Bit)] + \ m.ClockInterface(False, False) conv = m.DefineCircuit('Convolution', *args) # Line buffer declaration lb = Linebuffer(cirb, in_LB, out_LB, imgType, True) m.wire(conv.I0, lb.I) m.wire(conv.WE, lb.wen) # MAC declaration mac = MAC(x * y) # connect up linebuffer and weights to MAC input k = 0 for i in range(y): for j in range(x): m.wire(lb.out[i][j][0], mac.I0[k]) m.wire(conv.I1[i][j][0], mac.I1[k]) k += 1 m.wire(conv.O, mac.O) m.wire(conv.V, lb.valid) m.EndCircuit() module = GetCoreIRModule(cirb, conv) module.save_to_file("convolution.json") print("done")