MicroVM.scala 5.82 KB
Newer Older
1 2
package uvm.refimpl

Kunshan Wang's avatar
Kunshan Wang committed
3
import java.io.OutputStreamWriter
Kunshan Wang's avatar
Kunshan Wang committed
4 5
import java.io.Writer

Kunshan Wang's avatar
Kunshan Wang committed
6 7
import scala.collection.mutable.HashSet

8
import uvm._
Kunshan Wang's avatar
Kunshan Wang committed
9
import uvm.ir.irbuilder.IRBuilder
Kunshan Wang's avatar
Kunshan Wang committed
10
import uvm.ir.textinput.UIRTextReader
Kunshan Wang's avatar
Kunshan Wang committed
11
import uvm.ir.textoutput.BundleSerializer
Kunshan Wang's avatar
Kunshan Wang committed
12
import uvm.ir.textoutput.DebugBundleSerializer
Kunshan Wang's avatar
Kunshan Wang committed
13
import uvm.refimpl.bootimg.BootImageBuilder
Kunshan Wang's avatar
Kunshan Wang committed
14
import uvm.refimpl.bootimg.BootImageLoader
Kunshan Wang's avatar
Kunshan Wang committed
15
import uvm.refimpl.hail.HailScriptLoader
16 17
import uvm.refimpl.itpr._
import uvm.refimpl.mem._
Kunshan Wang's avatar
Kunshan Wang committed
18
import uvm.refimpl.nat.NativeCallHelper
Kunshan Wang's avatar
Kunshan Wang committed
19
import uvm.refimpl.nat.NativeLibraryHolder
20
import uvm.staticanalysis.StaticAnalyzer
21
import uvm.utils.IDFactory
22
import uvm.utils.WithUtils.tryWithResource
23 24

object MicroVM {
25 26
  val DEFAULT_SOS_SIZE: Word = 2L * 1024L * 1024L; // 2MiB
  val DEFAULT_LOS_SIZE: Word = 2L * 1024L * 1024L; // 2MiB
27 28
  val DEFAULT_GLOBAL_SIZE: Word = 1L * 1024L * 1024L; // 1MiB
  val DEFAULT_STACK_SIZE: Word = 63L * 1024L; // 60KiB per stack
29 30

  def apply(): MicroVM = {
Kunshan Wang's avatar
Kunshan Wang committed
31 32
    val vmConf = new VMConf()
    new MicroVM(vmConf)
33
  }
Kunshan Wang's avatar
Kunshan Wang committed
34

35
  def apply(confStr: String): MicroVM = {
Kunshan Wang's avatar
Kunshan Wang committed
36 37
    val vmConf = VMConf(confStr)
    new MicroVM(vmConf)
38 39
  }
}
Kunshan Wang's avatar
Kunshan Wang committed
40

Kunshan Wang's avatar
Kunshan Wang committed
41
class MicroVM(val vmConf: VMConf) {
42 43
  // implicitly injected resources
  private implicit val microVM = this
44

45
  val globalBundle = new GlobalBundle()
46
  val constantPool = new ConstantPool()
Kunshan Wang's avatar
Kunshan Wang committed
47
  val memoryManager = new MemoryManager(vmConf)
Kunshan Wang's avatar
Kunshan Wang committed
48 49

  private implicit val memorySupport = memoryManager.memorySupport
Kunshan Wang's avatar
Kunshan Wang committed
50

Kunshan Wang's avatar
Kunshan Wang committed
51
  val nativeLibraryHolder = NativeLibraryHolder(vmConf.extraLibs: _*)
Kunshan Wang's avatar
Kunshan Wang committed
52

53
  implicit val nativeCallHelper = new NativeCallHelper()
Kunshan Wang's avatar
Kunshan Wang committed
54

55
  val threadStackManager = new ThreadStackManager()
56

57
  val trapManager = new TrapManager()
Kunshan Wang's avatar
Kunshan Wang committed
58
  val contexts = new HashSet[MuCtx]()
Kunshan Wang's avatar
Kunshan Wang committed
59

Kunshan Wang's avatar
Kunshan Wang committed
60
  val idFactory = IDFactory.newClientIDFactory()
Kunshan Wang's avatar
Kunshan Wang committed
61
  val irBuilderRegistry = new SequentialObjectKeeper[IRBuilder]()
Kunshan Wang's avatar
Kunshan Wang committed
62 63
  val irReader = new UIRTextReader(idFactory, recordSourceInfo = vmConf.sourceInfo)
  val hailScriptLoader = new HailScriptLoader(recordSourceInfo = vmConf.sourceInfo)
64
  val staticAnalyzer = new StaticAnalyzer()
Kunshan Wang's avatar
Kunshan Wang committed
65

66
  val bootImageBuilder = new BootImageBuilder()
Kunshan Wang's avatar
Kunshan Wang committed
67

68
  {
Kunshan Wang's avatar
Kunshan Wang committed
69 70
    // VOID, BYTE, BYTE_ARRAY: The micro VM allocates stacks on the heap in the large object space.
    // It is represented as a big chunk of byte array.
71
    // So the GC must know about this type because the GC looks up the globalBundle for types.
Kunshan Wang's avatar
Kunshan Wang committed
72 73 74 75 76 77 78 79 80

    // BYTES, BYTES_R, REFS, REFS_R: Types for the @uvm.meta.* common instructions.

    import InternalTypes._
    for (ty <- Seq(VOID, BYTE, BYTE_ARRAY, BYTES, BYTES_R, REFS, REFS_R)) {
      globalBundle.typeNs.add(ty)
    }

    // Some internal constants needed by the HAIL loader
81

Kunshan Wang's avatar
Kunshan Wang committed
82 83 84 85
    for (c <- Seq(NULL_REF_VOID, NULL_IREF_VOID, NULL_FUNCREF_VV, NULL_THREADREF, NULL_STACKREF)) {
      globalBundle.constantNs.add(c)
      constantPool.addGlobalVar(c)
    }
86 87 88 89 90 91 92
    
    // Some types required by the RunMu class
    
    for (ty <- Seq(C_INT, C_CHAR, C_CHARP, C_CHARPP)) {
      globalBundle.typeNs.add(ty)
    }
    
93
  }
94 95 96 97

  /**
   * Add things from a bundle to the Micro VM.
   */
98
  def addBundle(bundle: TrantientBundle) {
99 100 101 102 103
    if (vmConf.dumpBundle) {
      val dbs = new DebugBundleSerializer(bundle)
      dbs.writeUIR(new OutputStreamWriter(System.err))
    }

104 105 106
    if (vmConf.staticCheck) {
      staticAnalyzer.checkBundle(bundle, Some(globalBundle))
    }
107

108 109 110 111 112
    globalBundle.merge(bundle);

    for (gc <- bundle.globalCellNs.all) {
      memoryManager.globalMemory.addGlobalCell(gc)
    }
113
    for (ef <- bundle.expFuncNs.all) {
114
      nativeCallHelper.exposeFuncStatic(ef)
115 116
    }
    // Must allocate the memory and expose the functions before making constants.
117 118 119 120
    for (g <- bundle.globalVarNs.all) {
      constantPool.addGlobalVar(g)
    }
  }
Kunshan Wang's avatar
Kunshan Wang committed
121 122

  private val contextIDFactory = IDFactory.newOneBasedIDFactory()
Kunshan Wang's avatar
Kunshan Wang committed
123

124
  /**
Kunshan Wang's avatar
Kunshan Wang committed
125
   * Create a new MuCtx. Part of the API.
126
   */
127 128 129 130 131 132 133 134 135
  def newContext(): MuCtx = newContext("user")

  /**
   * Create a new MuCtx. Extended to add a name for debugging.
   */
  def newContext(name: String): MuCtx = {
    val id = contextIDFactory.getID()
    val mutator = microVM.memoryManager.heap.makeMutator("MuCtx-%d-%s".format(id, name)) // This may trigger GC
    val ca = new MuCtx(id, mutator)
Kunshan Wang's avatar
Kunshan Wang committed
136
    contexts.add(ca)
Kunshan Wang's avatar
Kunshan Wang committed
137 138
    ca
  }
139 140 141
  /**
   * Given a name, get the ID of an identified entity.
   */
Kunshan Wang's avatar
Kunshan Wang committed
142
  def idOf(name: MuName): MuID = globalBundle.allNs(name).id
Kunshan Wang's avatar
Kunshan Wang committed
143

144 145 146
  /**
   * Given an ID, get the name of an identified entity.
   */
Kunshan Wang's avatar
Kunshan Wang committed
147
  def nameOf(id: MuID): MuName = globalBundle.allNs(id).name.get
Kunshan Wang's avatar
Kunshan Wang committed
148

Kunshan Wang's avatar
Kunshan Wang committed
149 150 151 152 153 154
  /**
   * Set the trap handler.
   */
  def setTrapHandler(trapHandler: TrapHandler): Unit = {
    trapManager.trapHandler = trapHandler
  }
Kunshan Wang's avatar
Kunshan Wang committed
155

Kunshan Wang's avatar
Kunshan Wang committed
156 157 158
  /**
   * Make boot image.
   */
Kunshan Wang's avatar
Kunshan Wang committed
159
  def makeBootImage(whiteList: Seq[MuID], outputFile: String): Unit = {
160 161 162 163 164
    val whiteListObjs = whiteList.map { id =>
      val obj = globalBundle.allNs(id)
      obj match {
        case tl: TopLevel => tl
        case _ => throw new UvmRuntimeException(
Kunshan Wang's avatar
Kunshan Wang committed
165 166
          "White list may only contain top-level definitions. Entity ID %d%s is a %s".format(
            obj.id, obj.name.map(n => s" (${n})").getOrElse(""), obj.getClass.getName))
167 168
      }
    }
Kunshan Wang's avatar
Kunshan Wang committed
169

170
    bootImageBuilder.makeBootImage(whiteListObjs, outputFile)
Kunshan Wang's avatar
Kunshan Wang committed
171
  }
Kunshan Wang's avatar
Kunshan Wang committed
172

Kunshan Wang's avatar
Kunshan Wang committed
173
  /**
Kunshan Wang's avatar
Kunshan Wang committed
174
   * Print the global bundle to the writer w.
Kunshan Wang's avatar
Kunshan Wang committed
175 176
   */
  def debugPrintGlobalBundle(w: Writer): Unit = {
Kunshan Wang's avatar
Kunshan Wang committed
177
    val bs = new BundleSerializer(globalBundle, globalBundle.allTopLevels().toSet)
Kunshan Wang's avatar
Kunshan Wang committed
178 179
    bs.writeUIR(w)
  }
Kunshan Wang's avatar
Kunshan Wang committed
180 181 182 183 184 185 186 187

  /**
   * Print the global bundle to stderr.
   */
  def debugPrintGlobalBundle(): Unit = {
    debugPrintGlobalBundle(new OutputStreamWriter(System.err))
  }

Kunshan Wang's avatar
Kunshan Wang committed
188 189 190 191
  /**
   * Load from a boot image.
   */
  def loadBootImage(file: String): Unit = {
192 193 194
    tryWithResource(new BootImageLoader(file)) { bil =>
      bil.load()
    }
Kunshan Wang's avatar
Kunshan Wang committed
195
  }
Kunshan Wang's avatar
Kunshan Wang committed
196

Kunshan Wang's avatar
Kunshan Wang committed
197 198 199 200 201 202
  /**
   * Execute. This is the external pusher of the execution.
   */
  def execute(): Unit = {
    threadStackManager.execute()
  }
Kunshan Wang's avatar
Kunshan Wang committed
203 204 205 206 207 208 209

  // Automatically load the boot image if provided
  {
    vmConf.bootImg foreach { fileName =>
      loadBootImage(fileName)
    }
  }
210
}