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

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

Kunshan Wang's avatar
Kunshan Wang committed
5 6
import java.io.Writer

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

9
import uvm._
Kunshan Wang's avatar
Kunshan Wang committed
10
import uvm.ir.irbuilder.IRBuilder
Kunshan Wang's avatar
Kunshan Wang committed
11
import uvm.ir.textinput.UIRTextReader
Kunshan Wang's avatar
Kunshan Wang committed
12
import uvm.ir.textoutput.BundleSerializer
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 18
import uvm.refimpl.itpr._
import uvm.refimpl.mem._
import uvm.refimpl.mem.TypeSizes.Word
Kunshan Wang's avatar
Kunshan Wang committed
19
import uvm.refimpl.nat.NativeCallHelper
Kunshan Wang's avatar
Kunshan Wang committed
20
import uvm.refimpl.nat.NativeLibraryHolder
21
import uvm.staticanalysis.StaticAnalyzer
22
import uvm.utils.IDFactory
23
import uvm.utils.WithUtils.tryWithResource
24
import uvm.ir.textoutput.DebugBundleSerializer
25 26

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

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

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

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

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

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

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

55
  implicit val nativeCallHelper = new NativeCallHelper()
Kunshan Wang's avatar
Kunshan Wang committed
56

57
  val threadStackManager = new ThreadStackManager()
58

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

Kunshan Wang's avatar
Kunshan Wang committed
62
  val idFactory = IDFactory.newClientIDFactory()
63
  val irBuilder = new IRBuilder(globalBundle, idFactory)
64
  val irNodeRegistry = new SequentialObjectKeeper[IRNode]()
Kunshan Wang's avatar
Kunshan Wang committed
65 66
  val irReader = new UIRTextReader(idFactory, recordSourceInfo = vmConf.sourceInfo)
  val hailScriptLoader = new HailScriptLoader(recordSourceInfo = vmConf.sourceInfo)
67
  val staticAnalyzer = new StaticAnalyzer()
Kunshan Wang's avatar
Kunshan Wang committed
68

69
  val bootImageBuilder = new BootImageBuilder()
Kunshan Wang's avatar
Kunshan Wang committed
70

71
  {
Kunshan Wang's avatar
Kunshan Wang committed
72 73
    // 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.
74
    // So the GC must know about this type because the GC looks up the globalBundle for types.
Kunshan Wang's avatar
Kunshan Wang committed
75 76 77 78 79 80 81 82 83

    // 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
84

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

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

107 108 109
    if (vmConf.staticCheck) {
      staticAnalyzer.checkBundle(bundle, Some(globalBundle))
    }
110

111 112 113 114 115
    globalBundle.merge(bundle);

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

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

127
  /**
Kunshan Wang's avatar
Kunshan Wang committed
128
   * Create a new MuCtx. Part of the API.
129
   */
130 131 132 133 134 135 136 137 138
  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
139
    contexts.add(ca)
Kunshan Wang's avatar
Kunshan Wang committed
140 141
    ca
  }
142 143 144
  /**
   * Given a name, get the ID of an identified entity.
   */
Kunshan Wang's avatar
Kunshan Wang committed
145
  def idOf(name: MuName): MuID = globalBundle.allNs(name).id
Kunshan Wang's avatar
Kunshan Wang committed
146

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

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

Kunshan Wang's avatar
Kunshan Wang committed
159 160 161
  /**
   * Make boot image.
   */
Kunshan Wang's avatar
Kunshan Wang committed
162
  def makeBootImage(whiteList: Seq[MuID], outputFile: String): Unit = {
163 164 165 166 167
    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
168 169
          "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))
170 171
      }
    }
Kunshan Wang's avatar
Kunshan Wang committed
172

173
    bootImageBuilder.makeBootImage(whiteListObjs, outputFile)
Kunshan Wang's avatar
Kunshan Wang committed
174
  }
Kunshan Wang's avatar
Kunshan Wang committed
175

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

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

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

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

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