Import.scala 5.96 KB
Newer Older
1
2
3
//
// Copyright (C) 2014 Jens Korinth, TU Darmstadt
//
4
// This file is part of Tapasco (TPC).
5
//
6
// Tapasco is free software: you can redistribute it and/or modify
7
8
9
10
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
11
// Tapasco is distributed in the hope that it will be useful,
12
13
14
15
16
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
17
// along with Tapasco.  If not, see <http://www.gnu.org/licenses/>.
18
19
20
21
22
23
24
25
26
27
//
/**
 * @file     Import.scala
 * @brief    The Import activity import an IP-XACT IP core in a .zip file
 *           into the currently configured core library for TPC. If no
 *           synthesis report can be found, it will use the EvaluateIP
 *           activity to generate an out-of-context synthesis report to
 *           estimate area utilization and max. operating frequency.
 * @authors  J. Korinth, TU Darmstadt (jk@esa.cs.tu-darmstadt.de)
 **/
28
29
30
31
32
package de.tu_darmstadt.cs.esa.tapasco.activity
import  de.tu_darmstadt.cs.esa.tapasco.base._
import  de.tu_darmstadt.cs.esa.tapasco.base.json._
import  de.tu_darmstadt.cs.esa.tapasco.util._
import  de.tu_darmstadt.cs.esa.tapasco.filemgmt.FileAssetManager
33
34
35
36
37
38
39
40
41
import  java.nio.file._

/**
 * The Import activity imports an existing IP-XACT core into the cores library
 * of the current TPC configuration. Reports can either be supplied manually,
 * or will be generated by out-of-context synthesis, if not found.
 **/
object Import {
  private implicit final val logger =
42
    de.tu_darmstadt.cs.esa.tapasco.Logging.logger(getClass)
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60

  /**
   * Import the given IP-XACT .zip file as Kernel with given id for the given target.
   * If no XML synthesis report is found (%NAME%_export.xml), will perform out-of-contex
   * synthesis and place-and-route for the Core to produce area and Fmax estimates.
   * @param zip Path to IP-XACT. zip.
   * @param id Kernel ID.
   * @param t Target Architecture + Platform combination to import for.
   * @param acc Average clock cycle count for a job execution on the PE (optional).
   * @param cfg Implicit [[base.Configuration]].
   **/
  def apply(zip: Path, id: Kernel.Id, t: Target, acc: Option[Int])(implicit cfg: Configuration): Boolean = {
    // get VLNV from the file
    val vlnv = VLNV.fromZip(zip)
    logger.trace("found VLNV in zip " + zip + ": " + vlnv)
    // extract version and name from VLNV, create Core
    val c = Core(
        descPath = zip.resolveSibling("core.description"),
61
        _zipPath = zip.getFileName,
62
63
64
65
        name = vlnv.name,
        id = id,
        version = vlnv.version.toString,
        _target = t,
66
        Some("imported from %s on %s".format(zip.toAbsolutePath.toString, java.time.LocalDateTime.now().toString)),
67
68
69
        acc)

    // write core.description to output directory (as per config)
70
71
    val p = cfg.outputDir(c, t).resolve("ipcore").resolve("core.description")
    importCore(c, t, p)
72
73
74
75
76
77
78
79
80
81
  }

  /**
   * Imports the IP-XACT .zip to the default path structure (ipcore/) and performs
   * out-of-context synthesis (if no report from HLS was found).
   * @param c Core description.
   * @param t Target platform and architecture.
   * @param p Output path for core description file.
   * @param cfg Implicit [[Configuration]].
   **/
82
  private def importCore(c: Core, t: Target, p: Path)(implicit cfg: Configuration): Boolean = {
83
    Files.createDirectories(p.getParent)
84
    logger.trace("created output directories: {}", p.getParent.toString)
85
86

    // add link to original .zip in the 'ipcore' subdir
87
88
    val linkp = cfg.outputDir(c, t).resolve("ipcore").resolve(c.zipPath.getFileName.toString)
    if (! linkp.toFile.equals(c.zipPath.toAbsolutePath.toFile)) {
89
90
      Files.createDirectories(linkp.getParent)
      logger.trace("created directories: {}", linkp.getParent.toString)
91
92
93
94
95
96
97
98
99
100
101
102
      if (linkp.toFile.exists) {
        logger.debug("file {} already exists, skipping copy/link step")
      } else {
        logger.trace("creating symbolic link {} -> {}", linkp: Any, c.zipPath.toAbsolutePath)
        try   { java.nio.file.Files.createSymbolicLink(linkp, c.zipPath.toAbsolutePath) }
        catch { case ex: java.nio.file.FileSystemException => {
          logger.warn("cannot create link {} -> {}, copying data", linkp: Any, c.zipPath)
          java.nio.file.Files.copy(c.zipPath, linkp, java.nio.file.StandardCopyOption.REPLACE_EXISTING)
        }}
      }
    } else {
      logger.debug("{} is the same as {}, no copy/link required", linkp: Any, c.zipPath.toAbsolutePath)
103
104
105
    }

    // finally, evaluate the ip core and store the report with the link
106
    val res = evaluateCore(c, t)
107
108
109
110
111
112
113
114
115
116
117
118
119
120

    // write core.description
    logger.debug("writing core description: {}", p.toString)
    Core.to(c, p)
    res
  }

  /**
   * Searches for an existing synthesis report, otherwise performs out-of-context synthesis and
   * place-and-route to produce area and Fmax estimates
   * @param c Core description.
   * @param t Target Architecture + Platform combination.
   * @param cfg Implicit [[Configuration]].
   **/
121
  private def evaluateCore(c: Core, t: Target)(implicit cfg: Configuration): Boolean = {
122
123
124
125
126
127
128
129
130
131
132
    logger.trace("looking for SynthesisReport ...")
    val period = 1000.0 / t.pd.supportedFrequencies.sortWith(_>_).head
    val report = cfg.outputDir(c, t).resolve("ipcore").resolve("%s_export.xml".format(c.name))
    FileAssetManager.reports.synthReport(c.name, t) map { hls_report =>
      logger.trace("found existing synthesis report: " + hls_report)
      if (! report.equals(hls_report.file)) { // make link if not same
        java.nio.file.Files.createSymbolicLink(report, hls_report.file.toAbsolutePath)
      }
      true
    } getOrElse {
      logger.info("SynthesisReport for {} not found, starting evaluation ...", c.name)
133
      EvaluateIP(c.zipPath, period, t.pd.part, report)
134
135
136
    }
  }
}