func CreateLayer(
        lib *cuda.CudaGenerator, 
        conf Conf, 
        prevLayer cuda.Layer, 
        dtype base.Dtype) cuda.Layer {
    config := conf.Clone()
    layerType := config.GetString("layer")
    delete(config, "layer")
    config["dtype"] = dtype
    common := config["common"]
    delete(config, "common")
    if common != nil {
        config.Update(common.(Conf))
    }
    if prevLayer != nil {
        config["N"] = prevLayer.N()
        _, isPrevFullLayer := prevLayer.(*cuda.FullLayer)
        switch {
        case layerType == "FullLayer":
            config["nIn"] = prevLayer.NOut()
        case layerType == "PoolLayer" && isPrevFullLayer:
            config["C"] = prevLayer.NOut()
        case layerType == "BatchNorm" && isPrevFullLayer:
            config["nIn"] = prevLayer.NOut()
        default:
            config["C"] = prevLayer.K()
            config["D"] = prevLayer.M()
            config["H"] = prevLayer.P()
            config["W"] = prevLayer.Q()
            if layerType == "Inception" {
                partitions := config["partitions"].([][]Conf)
                configK := 0
                var configPartitions [][]cuda.Layer
                for _, part := range partitions {
                    var layerSequence []cuda.Layer
                    last := prevLayer
                    for _, layerConf := range part {
                        last = CreateLayer(lib, layerConf, last, dtype)
                        layerSequence = append(layerSequence, last)
                    }
                    configPartitions = append(configPartitions, layerSequence)
                    configK += last.K()
                    if _, ok := config["P"]; ok {
                        base.Assert(
                            config.GetInt("P") == last.P() && 
                            config.GetInt("Q") == last.Q())
                    } else {
                        config["M"] = last.M()
                        config["P"] = last.P()
                        config["Q"] = last.Q()
                    }
                }
                config["K"] = configK
                config["partitions"] = configPartitions
            }
        }
    }
    switch layerType {
    case "DataLayer":
        return CreateDataLayer(lib, config)
    case "ConvLayer":
        return CreateConvLayer(lib, config)
    case "PoolLayer":
        return CreatePoolLayer(lib, config)
    case "FullLayer":
        return CreateFullLayer(lib, config)
    case "Inception":
        return CreateInception(lib, config)
    case "BatchNorm":
        return CreateBatchNorm(lib, config)
    default:
        base.ValueError("Invalid layer type:  %s", layerType)
    }
    return nil
}
Layer constructor (originally in backends/layer_gpu.py)
package main
import (
    "fmt"
    "fragata/arhat/backends"
    "fragata/arhat/base"
    "fragata/arhat/generators/cuda"
    "os"
    "strings"
)
var (
    computeCapability = [2]int{6, 0}
)
var (
    loops = 10
    layerBench = false
    printStats = false
    zeros = false
    verbose = true
)
type Conf map[string]interface{}
func(c Conf) Clone() Conf {
    r := make(Conf)
    for k, v := range c {
        r[k] = v
    }
    return r
}
func(c Conf) Update(other Conf) {
    for k, v := range other {
        c[k] = v
    }
}
func(c Conf) GetBool(key string) bool {
    val, ok := c[key]
    if !ok {
        return false
    }
    return val.(bool)
}
func(c Conf) GetInt(key string) int {
    val, ok := c[key]
    if !ok {
        return base.IntNone
    }
    return val.(int)
}
func(c Conf) GetString(key string) string {
    val, ok := c[key]
    if !ok {
        return ""
    }
    return val.(string)
}
var (
    conv11    = Conf{"R": 11, "S": 11, "pad_h": 2, "pad_w": 2, "str_h": 4, "str_w": 4}
    conv11p0  = Conf{"R": 11, "S": 11, "pad_h": 0, "pad_w": 0, "str_h": 4, "str_w": 4}
    conv7     = Conf{"R": 7,  "S": 7,  "pad_h": 3, "pad_w": 3, "str_h": 2, "str_w": 2}
    conv5     = Conf{"R": 5,  "S": 5,  "pad_h": 2, "pad_w": 2}
    conv5p0   = Conf{"R": 5,  "S": 5,  "pad_h": 0, "pad_w": 0}
    conv3     = Conf{"R": 3,  "S": 3,  "pad_h": 1, "pad_w": 1}
    conv2     = Conf{"R": 2,  "S": 2,  "pad_h": 0, "pad_w": 0, "str_h": 2, "str_w": 2}
    conv1     = Conf{"R": 1,  "S": 1,  "pad_h": 0, "pad_w": 0}
)
var (
    pool2s2p0 = Conf{"R": 2, "S": 2}
    pool3s2p0 = Conf{"R": 3, "S": 3, "str_h": 2, "str_w": 2}
    pool3s2p1 = Conf{"R": 3, "S": 3, "str_h": 2, "str_w": 2, "pad_h": 1, "pad_w": 1}
    pool3s1p1 = Conf{"R": 3, "S": 3, "str_h": 1, "str_w": 1, "pad_h": 1, "pad_w": 1}
    pool7s1p0 = Conf{"R": 7, "S": 7, "str_h": 1, "str_w": 1}
)
var (
    pool1j2 = Conf{"op": "max", "J": 2}  
    pool2j2 = Conf{"op": "max", "J": 2, "R": 2, "S": 2}
    pool3j2 = Conf{"op": "max", "J": 2, "R": 3, "S": 3}
)