예제 #1
0
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
예제 #2
0
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
예제 #3
0
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
예제 #4
0
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
예제 #5
0
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)
예제 #6
0
        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")
예제 #7
0
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")
예제 #8
0
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")
예제 #9
0
# 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")
예제 #10
0
def save_CoreIR_json(cirb, module, file):
    mod = GetCoreIRModule(cirb, module)
    mod.save_to_file(file)
예제 #11
0
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")