Пример #1
0
def product(env, outputs, rule, inputs = None, implicit = None,
            order_only = None):
  def _process(v, ek, d, dk):
    if v is None:
      v = env.get(ek, None)
    else:
      v = v + env.get(ek, [])

    if v:
      d[dk] = v

  delta = [
    cobble.env.remove('__implicit__'),
    cobble.env.remove('__order_only__'),
  ]
  p = {
    'outputs': outputs,
    'rule': rule,
    'inputs': inputs,
    'variables': env.derive(delta).dict_copy(),
  }
  _process(implicit, '__implicit__', p, 'implicit')
  _process(order_only, '__order_only__', p, 'order_only')

  return p
Пример #2
0
 def derive_down(self, env):
     """Derives the down-environment, that is, the environment seen by
     dependencies of this target."""
     if self.concrete:
         # Concrete targets use function-deltas to entirely replace the
         # provided environment. Since we checked that in the constructor,
         # we'll just call the delta directly. This allows concrete targets
         # to be given None as an environment.
         return self._down(env)
     else:
         return env.derive(self._down)
Пример #3
0
  def _compile_object(self, source, env):
    ext = os.path.splitext(source)[1]
    rule, keys = self._file_type_map[ext]

    keys = _compile_keys | frozenset(keys)

    o_env = env.derive(chain(self._deps_delta(env),
                             [ cobble.env.subset(keys) ]))
    return cobble.product(o_env,
      outputs = [ self.package.outpath(o_env, source + '.o') ],
      rule = rule,
      inputs = [ self.package.inpath(source) ],
    )
Пример #4
0
    def mkusing(ctx):
        # Resolve the module a Bluesim object file.
        top_path = ctx.rewrite_sources([top])[0]

        # Make sure top looks like a Bluespec package file.
        ext_re = re.compile(r'.ba$')
        assert ext_re.search(top_path), \
            '%s does not appear to be a .ba object file' % top_path

        top_module = ext_re.split(os.path.basename(top_path))[0]

        # Derive a new environment for the Bluesim binary output path. Note: this environment
        # could/should probably be refined.
        env = ctx.env.subset_require(_compile_keys).derive({
            # Make the output a bit more unique. See above.
            SOURCE_HACK.name: [top_path],
            BSC_FLAGS.name: ['-sim', '-e', top_module],
        })

        # Force the creation of the output dir so as to keep BSC from yelling.
        stamp = cobble.target.Product(
            env=ctx.env.subset([]),
            outputs=[package.outpath(env, '.force-dir-creation')],
            rule='bluespec_directory_creation_hack',
        )

        # Set up the env for the Bluesim output.
        out_dir = package.outpath(env)
        script_path = package.outpath(env, name)
        so_name = name + '.so'
        so_path = package.outpath(env, so_name)
        p_env = env.derive({
            BSC_FLAGS.name: [
                '-simdir',
                out_dir,
            ],
        })

        simulation = cobble.target.Product(
            env=p_env,
            inputs=[top_path],
            outputs=([script_path], [so_path]),
            rule='link_bluesim_binary',
            order_only=stamp.outputs,
        )
        simulation.expose(path=script_path, name='script')
        simulation.symlink(target=script_path, source=package.linkpath(name))
        simulation.expose(path=so_path, name='so')
        simulation.symlink(target=so_path, source=package.linkpath(so_name))

        return (local, [simulation, stamp])
Пример #5
0
 def _derive_down(self, env_up):
   env = self.package.project.named_envs[self.environment]
   return env.derive(self._extra_delta)
Пример #6
0
 def derive_local(self, env):
     """Derives the local-environment provided to using_and_products."""
     return env.derive(self._local)
Пример #7
0
def _compile_objects(package, sources, ctx):
    """Implementation factor for targets that compile .bs/.bsv to .bo.

    This operation returns a tuple of products '(objects, dyndeps, dd_map,
    stamp)', where

    - 'objects' is a list of object file products.
    - 'dyndeps' is a list of dyndeps file products.
    - 'dd_map' is a list of local "Module=Path" mappings for bluescan.
    - 'stamp' is a product that will deposit a zero-length file into the build
      output directory, to quiet bsc.
    """
    sources_i = ctx.rewrite_sources(sources)

    # Filter out irrelevant environment information. This initially subsetted
    # environment is used to select the output directory.
    env = ctx.env.subset_require(_compile_keys).derive({
        # Insert the list of sources in the directory to make package output
        # dirs more unique. See comment at top.
        SOURCE_HACK.name:
        sources_i,
    })

    # Construct the .bo search path
    unique_bo_paths = sorted(env[BO_PATHS.name])

    bsc_flags = ['-p +:' + ':'.join(unique_bo_paths)]
    # Extend the environment with the arguments to the compile_bluespec_obj
    # rule and produce our compilation product.
    p_env = env.derive({
        BSC_FLAGS.name: bsc_flags,
        BSC_BDIR.name: package.outpath(env),
    })

    bos = []
    dyndeps = []
    for (source, orig) in zip(sources_i, sources):
        # Construct the path to the new .bo
        output = package.outpath(
            env,
            os.path.splitext(os.path.basename(source))[0] + '.bo')
        # Derive the path of the generated dyndep file.
        dyndep_path = output + '.dyndep'
        bos.append(
            cobble.target.Product(
                env=p_env,
                outputs=[output],
                rule='compile_bluespec_obj',
                inputs=[source],
                order_only=[dyndep_path],
                dyndep=dyndep_path,
            ))

    # Generate the local portion of the dyndep map, so that modules in this
    # library can depend on each other if required.
    local_map = set(_mapping(bo.outputs[0]) for bo in bos)
    scan_env_proto = ctx.env.subset_require(_bluescan_keys).derive({
        BLUESCAN_MAP.name:
        local_map,
    })

    for bo in bos:
        source = bo.inputs[0]
        output = bo.outputs[0]
        # Re-derive the environment narrowed down to the bluescan arguments.
        scan_env = scan_env_proto.derive({
            BLUESCAN_OBJ.name: output,
        })

        dyndeps.append(
            cobble.target.Product(
                env=scan_env,
                outputs=[bo.dyndep],
                rule='bluespec_dep_scan',
                inputs=[source],
            ))

    # bsc won't give us precise dependency information, but is happy to
    # complain endlessly when we suggest a search path that doesn't yet exist
    # (because we were being overly conservative with our dependency
    # information since it wouldn't help us). To silence this nonsense, we
    # force creation of a meaningless file in every build dir, and propagate it
    # as an implicit.
    empty_env = env.subset([])
    stamp = cobble.target.Product(
        env=empty_env,
        outputs=[package.outpath(env, '.force-dir-creation')],
        rule='bluespec_directory_creation_hack',
    )

    return (bos, dyndeps, local_map, stamp)
Пример #8
0
    def mkusing(ctx):
        # Resolve the top package or object to a file.
        top_path = ctx.rewrite_sources([top])[0]

        # Make sure top looks like a reasonable input file.
        ext_re = re.compile(r'.bsv?$')
        assert ext_re.search(
            top_path), '%s does not appear to be a .bs or .bsv file' % top_path

        top_package = ext_re.split(os.path.basename(top_path))[0]

        # Make sure arguments make sense and we do not generate garbage.
        assert len(modules) != 0, 'No modules provided, output will be empty'
        assert mod_type == 'verilog' or mod_type == 'sim', 'Invalid module type %s' % mod_type

        # When generating Verilog output, BSC expects a package file as input. It will compile this
        # package into an object, whether or not it may already be able to find an object for this
        # package. The package file may or may not already be part of the dependency tree and if it
        # is we do not want to overwrite it since that may trigger re-compilation of other targets.
        #
        # To work around this, derive an environment which is sufficiently different and have BSC
        # write out the object on the side, using it only for this target.
        #
        # Note that if the package is already present in the dependency tree, BSC will be able to
        # use either since we can't remove the .bo path for the other object (as there may be other
        # objects on that path). This is not ideal, but since both objects are built using the same
        # flags they should be identical for the purposes of generating the desired Verilog output.

        # Rewrite outputs into the environment.
        object_out = ctx.env.rewrite(top_package + '.bo')
        module_outs = [ctx.env.rewrite(m) for m in modules]

        env = ctx.env.subset_require(_compile_keys).derive({
            # Insert the list of output modules to make package output dirs more unique. This allows
            # for generating Verilog modules from the same package in two different rules if this is
            # desired for some reason.
            #
            # Note that any (* synthesize *) directives in the package will still cause other
            # modules to be generated and written to disk, but they will not be exposed in the build
            # graph unless includes in the modules argument.
            SOURCE_HACK.name: [top_path] + module_outs,
            BSC_FLAGS.name: [
                '-p +:' + ':'.join(sorted(ctx.env[BO_PATHS.name])),
                '-%s' % mod_type,
            ],
        })

        # Derive the output path and the subsequent product env using this output path for both the
        # package object and Verilog modules.
        out_dir = package.outpath(env)
        object_path = os.path.join(out_dir, object_out)
        module_ext = '.v' if mod_type == 'verilog' else '.ba'
        module_paths = [
            os.path.join(out_dir, out + module_ext) for out in module_outs
        ]

        p_env = env.derive({
            BSC_FLAGS.name:
            ['-vdir', out_dir] if mod_type == 'verilog' else [],
            BSC_BDIR.name:
            out_dir,
        })

        # Derive dyndep env and product for the dyndep file.
        dyndep_out = object_out + '.dyndep'
        dyndep_path = os.path.join(out_dir, dyndep_out)
        dyndep_env = ctx.env.subset_require(_bluescan_keys).derive({
            BLUESCAN_OBJ.name:
            object_path,
        })

        dyndep = cobble.target.Product(
            env=dyndep_env,
            inputs=[top_path],
            outputs=[dyndep_path],
            rule='bluespec_dep_scan',
        )

        # Make sure the vdir/bdir exists by adding a stamp.
        vdir_stamp = cobble.target.Product(
            env=ctx.env.subset([]),
            outputs=[os.path.join(out_dir, '.force-dir-creation')],
            rule='bluespec_directory_creation_hack',
        )

        product = cobble.target.Product(
            env=p_env,
            inputs=[top_path],
            outputs=module_paths + [object_path],
            rule='generate_bluespec_modules',
            dyndep=dyndep_path,
            order_only=vdir_stamp.outputs + dyndep.outputs,
        )
        for name, path in zip(module_outs, module_paths):
            product.expose(path=path, name=name)

        our_using = (
            using,
            cobble.env.prepare_delta({
                '__implicit__': module_paths,
            }),
        )

        return (our_using, [vdir_stamp, product, dyndep])