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

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

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

7
import uvm._
Kunshan Wang's avatar
Kunshan Wang committed
8 9
import uvm.ir.irbuilder.IRBuilder
import uvm.ir.irbuilder.IRNode
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.refimpl.bootimg.BootImageBuilder
Kunshan Wang's avatar
Kunshan Wang committed
13
import uvm.refimpl.hail.HailScriptLoader
14 15 16
import uvm.refimpl.itpr._
import uvm.refimpl.mem._
import uvm.refimpl.mem.TypeSizes.Word
Kunshan Wang's avatar
Kunshan Wang committed
17
import uvm.refimpl.nat.NativeCallHelper
Kunshan Wang's avatar
Kunshan Wang committed
18
import uvm.refimpl.nat.NativeLibraryHolder
19
import uvm.staticanalysis.StaticAnalyzer
20
import uvm.utils.IDFactory
Kunshan Wang's avatar
Kunshan Wang committed
21
import uvm.utils.SequentialIDFactory
22 23

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

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

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

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

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

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

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

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

54
  val threadStackManager = new ThreadStackManager()
55

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

Kunshan Wang's avatar
Kunshan Wang committed
59
  val idFactory = IDFactory.newClientIDFactory()
60
  val irBuilder = new IRBuilder(globalBundle, idFactory)
61
  val irNodeRegistry = new SequentialObjectKeeper[IRNode]()
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

  /**
   * Add things from a bundle to the Micro VM.
   */
91
  def addBundle(bundle: TrantientBundle) {
92 93 94
    if (vmConf.staticCheck) {
      staticAnalyzer.checkBundle(bundle, Some(globalBundle))
    }
95

96 97 98 99 100
    globalBundle.merge(bundle);

    for (gc <- bundle.globalCellNs.all) {
      memoryManager.globalMemory.addGlobalCell(gc)
    }
101
    for (ef <- bundle.expFuncNs.all) {
102
      nativeCallHelper.exposeFuncStatic(ef)
103 104
    }
    // Must allocate the memory and expose the functions before making constants.
105 106 107 108
    for (g <- bundle.globalVarNs.all) {
      constantPool.addGlobalVar(g)
    }
  }
Kunshan Wang's avatar
Kunshan Wang committed
109 110

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

112
  /**
Kunshan Wang's avatar
Kunshan Wang committed
113
   * Create a new MuCtx. Part of the API.
114
   */
115 116 117 118 119 120 121 122 123
  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
124
    contexts.add(ca)
Kunshan Wang's avatar
Kunshan Wang committed
125 126
    ca
  }
127 128 129
  /**
   * Given a name, get the ID of an identified entity.
   */
Kunshan Wang's avatar
Kunshan Wang committed
130
  def idOf(name: String): Int = globalBundle.allNs(name).id
Kunshan Wang's avatar
Kunshan Wang committed
131

132 133 134
  /**
   * Given an ID, get the name of an identified entity.
   */
Kunshan Wang's avatar
Kunshan Wang committed
135
  def nameOf(id: Int): String = globalBundle.allNs(id).name.get
Kunshan Wang's avatar
Kunshan Wang committed
136

Kunshan Wang's avatar
Kunshan Wang committed
137 138 139 140 141 142
  /**
   * Set the trap handler.
   */
  def setTrapHandler(trapHandler: TrapHandler): Unit = {
    trapManager.trapHandler = trapHandler
  }
Kunshan Wang's avatar
Kunshan Wang committed
143

Kunshan Wang's avatar
Kunshan Wang committed
144 145 146 147
  /**
   * Make boot image.
   */
  def makeBootImage(whiteList: Seq[Int], outputFile: String): Unit = {
148 149 150 151 152
    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
153 154
          "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))
155 156
      }
    }
Kunshan Wang's avatar
Kunshan Wang committed
157

158
    bootImageBuilder.makeBootImage(whiteListObjs, outputFile)
Kunshan Wang's avatar
Kunshan Wang committed
159
  }
Kunshan Wang's avatar
Kunshan Wang committed
160

Kunshan Wang's avatar
Kunshan Wang committed
161
  /**
Kunshan Wang's avatar
Kunshan Wang committed
162
   *
Kunshan Wang's avatar
Kunshan Wang committed
163 164
   */
  def debugPrintGlobalBundle(w: Writer): Unit = {
Kunshan Wang's avatar
Kunshan Wang committed
165
    val bs = new BundleSerializer(globalBundle, globalBundle.allTopLevels().toSet)
Kunshan Wang's avatar
Kunshan Wang committed
166 167
    bs.writeUIR(w)
  }
Kunshan Wang's avatar
Kunshan Wang committed
168

Kunshan Wang's avatar
Kunshan Wang committed
169 170 171 172 173 174
  /**
   * Execute. This is the external pusher of the execution.
   */
  def execute(): Unit = {
    threadStackManager.execute()
  }
175
}