Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add RocketCore #705

Merged
merged 101 commits into from
Aug 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
101 commits
Select commit Hold shift + click to select a range
bec73b3
[build system] add rocketv build target
sequencer Jun 27, 2024
ad3b2ee
[build system] implement the generic Elaborator trait
sequencer Jun 25, 2024
7d3d685
[build system] add rocketv to elaborator
sequencer Jun 27, 2024
34f3db0
[rocketv] copy ALU into rocketv project
sequencer Jun 27, 2024
4f5c0f8
[rocketv] migrate ALU
sequencer Jun 27, 2024
710782e
[rocketv] add elaborator for ALU
sequencer Jun 27, 2024
b5a3604
[rocketv] copy AMOALU into rocketv project
sequencer Jun 27, 2024
b223612
[rocketv] migrate AMOALU
sequencer Jun 27, 2024
7c8dd8a
[rocketv] add elaborator for AMOALU
sequencer Jun 27, 2024
a386d80
[rocketv] copy Breakpoint into rocketv project
sequencer Jun 27, 2024
15b81a9
[rocketv] migrate BreakpointUnit
sequencer Jun 27, 2024
e614726
[rocketv] add elaborator for BreakpointUnit
sequencer Jun 27, 2024
c1201b6
[rocketv] copy BTB into rocketv project
sequencer Jun 27, 2024
9d0f937
[rocketv] migrate PopCountAtLeast
sequencer Jun 27, 2024
1f1d3d7
[rocketv] copy ReplacementPolicy into rocketv project
sequencer Jun 30, 2024
8da706f
[rocketv] migrate Replacement
sequencer Jun 30, 2024
f84ce93
[rocketv] migrate BTB
sequencer Jun 27, 2024
b04129f
[rocketv] add elaborator for BTB
sequencer Jun 27, 2024
3e926f7
[rocketv] copy CSR into rocketv project
sequencer Jun 27, 2024
d3a7381
[rocketv] migrate CSR
sequencer Jun 28, 2024
66a3051
[rocketv] add elaborator for CSR
sequencer Jun 28, 2024
07ae7a7
[rocketv] migrate Decoder
sequencer Jun 29, 2024
c3e0577
[rocketv] add elaborator for Decoder
sequencer Jun 29, 2024
616f4a4
[rocketv] copy RVCExpander into rocketv project
sequencer Jun 29, 2024
f06815c
[rocketv] migrate RVCExpander
sequencer Jun 29, 2024
046f66c
[rocketv] add elaborator for RVCExpander
sequencer Jun 29, 2024
b3fe074
[rocketv] copy IBuf into rocketv project
sequencer Jun 29, 2024
5982e2c
[rocketv] migrate IBuf
sequencer Jun 29, 2024
aef7984
[rocketv] add elaborator for IBuf
sequencer Jun 29, 2024
806917c
[rocketv] copy Multipler into rocketv project
sequencer Jun 29, 2024
3ad10c5
[rocketv] migrate MulDiv and PipelinedMultiplier
sequencer Jun 29, 2024
2db2c11
[rocketv] add elaborator for MulDiv and PipelinedMultiplier
sequencer Jun 29, 2024
c3eb590
[rocketv] copy PMA into rocketv project
sequencer Jun 29, 2024
073f8f2
[rocketv] migrate PMAChecker
sequencer Jun 29, 2024
c98261e
[rocketv] add elaborator for PMAChecker
sequencer Jun 29, 2024
78db6b8
[rocketv] copy PMP into rocketv project
sequencer Jun 29, 2024
f639817
[rocketv] migrate PMPChecker
sequencer Jun 29, 2024
ea15a63
[rocketv] add elaborator for PMAChecker
sequencer Jun 29, 2024
9b7106e
[rocketv] copy PTW into rocketv project
sequencer Jun 29, 2024
ee8df5c
[rocketv] copy ECC into rocketv project
qinjun-li Jun 28, 2024
e05824c
[rocketv] migrate PTW
sequencer Jun 30, 2024
65ac4a9
[rocketv] add elaborator for PTW
sequencer Jun 30, 2024
2543138
[rocketv] copy ICache into rocketv project
qinjun-li Jun 28, 2024
c1ba981
[rocketv] migrate ICache
qinjun-li Jun 28, 2024
ac0cc7e
[rocketv] add elaborator for ICache
qinjun-li Jun 28, 2024
41a24a3
[rocketv] copy FPU into rocketv project
sequencer Jun 30, 2024
517b3eb
[rocketv] migrate FPU
sequencer Jul 1, 2024
b75afeb
[rocketv] add elaborator for FPU
sequencer Jul 1, 2024
a3f1266
[rocketv] copy TLB into rocketv project
sequencer Jul 1, 2024
0a2b64d
[rocketv] migrate TLB
sequencer Jul 1, 2024
1974e1d
[rocketv] add elaborator for TLB
sequencer Jul 1, 2024
0837a93
[rocketv] copy DCache into rocketv project
qinjun-li Jul 1, 2024
551feb3
[rocketv] migrate DCache
qinjun-li Jul 1, 2024
eadaad4
[rocketv] add elaborator for DCache
qinjun-li Jul 1, 2024
c6497c4
[rocketv] copy Frontend into rocketv project
sequencer Jul 1, 2024
3b6925f
[rocketv] migrate Frontend
sequencer Jul 1, 2024
0ac092d
[rocketv] add elaborator for Frontend
sequencer Jul 2, 2024
fdf50ce
[rocketv] copy RocketCore into rocketv project
sequencer Jul 2, 2024
462fc19
[rocketv] migrate Rocket
sequencer Jul 3, 2024
5437355
[rocketv] add elaborator for Rocket
sequencer Jul 3, 2024
292765a
[rocketv] copy RocketTile into rocketv project
sequencer Jul 3, 2024
80ccae1
[rocketv] implementing RocketTile
sequencer Jul 4, 2024
3b59bf3
[rocketv] add elaborator for RocketTile
sequencer Jul 4, 2024
f63f915
[rocketv] add t1 specific logic
sequencer Aug 6, 2024
97a2722
[nix]: add rocketv derivation
Avimitin Jul 7, 2024
26cea7b
[nix] add rocketv-mlirbc
Avimitin Jul 7, 2024
4888e5d
[nix] add rocketv-rtl target
Avimitin Jul 7, 2024
a16667e
[nix] add new derivation rocketv-verilated-csrc
Avimitin Jul 7, 2024
c1ff4f5
[rocketemu] implement TestBench for RocketV Emulator
Avimitin Jul 8, 2024
6a35d96
[nix] add rocketv into elaborator source
Avimitin Jul 8, 2024
1251f93
[nix] use elaborator for Rocket generate
Avimitin Jul 8, 2024
d4775fa
[rocketemu] expose AXI4 agent as C-API
Avimitin Jul 10, 2024
e285351
[nix] add scope for rocketemu attribute
Avimitin Jul 10, 2024
18c0d27
[rocketemu] implemented rocket driver
Avimitin Jul 10, 2024
81001ee
[rocketemu] update TestBench implementation
Avimitin Jul 12, 2024
9b3c5be
[rocketemu] update DPI C binding
Avimitin Jul 12, 2024
a4497d9
[nix] add riscv-tests into overlay
Avimitin Jul 19, 2024
84ef932
[doc] add document about rocket emulator
Avimitin Jul 19, 2024
2c31cbc
[rocketemu] migrate AXI from master
Avimitin Jul 19, 2024
4abb0b8
[rocketemu] implement waveform generate
Avimitin Jul 19, 2024
9ca098f
[rocketemu] add missing watchdog call
Clo91eaf Jul 22, 2024
83e5bb5
[rocketemu] Requires a longer reset.
qinjun-li Jul 22, 2024
e03f77f
[rocketemu] fix wrong size
Clo91eaf Jul 22, 2024
85d5f5d
[rocketemu] refactor AXI read functions and remove the read alignment
Clo91eaf Jul 22, 2024
997d569
[rocketemu] add axi read burst in TestBench
Clo91eaf Jul 23, 2024
a97ec5a
[rocketv] fix DCache axi release.
qinjun-li Jul 23, 2024
2596268
[nix] use riscv32 embedded toolchain to compile riscv-tests
Avimitin Jul 23, 2024
6dfc31d
[rocketemu] fix trace build for driver
Avimitin Jul 23, 2024
f697288
[rocketemu] cycle should equals to tick / 20
Clo91eaf Jul 23, 2024
f457174
[rocketemu] add riscv test env
Clo91eaf Jul 23, 2024
fd0b6d1
[rocketemu] add quit functionality to terminate simulation
Clo91eaf Jul 24, 2024
a4cd734
[rocketemu] exit with right EXIT_CODE check
Clo91eaf Jul 24, 2024
a5d0f71
[rocketv] fix for rvdecoderdb bump
sequencer Jul 25, 2024
e9e2007
[rocketemu] add reg write event probe
Clo91eaf Jul 25, 2024
ef85f7a
[rocketemu] Add spike_rs, offline and test_common crates with depende…
Clo91eaf Jul 26, 2024
3e4f986
[nix] add difftest derivation for rocketv
Avimitin Jul 26, 2024
a6cd4c6
[rocketemu] set the resetvector(width: 64) using information from an …
PorterLu Jul 24, 2024
6a58a48
[rocketemu] add rustfmt
Clo91eaf Jul 27, 2024
7cb2983
[rocketemu] build rocket offline difftest
Clo91eaf Jul 27, 2024
caa36fd
[nix] refactor the rocketv subattr
Avimitin Aug 6, 2024
e9ec3b0
[nix] rename default config to "meowth"
Avimitin Aug 6, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,43 @@ If using clion,
$ nix develop .#t1.<config-name>.ip.emu -c clion ipemu/csrc
```

#### Rocket emulator

Rocket emulator contains multiple build phrase: RTL -> MLIR Bytecode ->
system verilog -> verilated C sources -> Rust emulator.

Most of the developer doesn't need to care about MLIR, system verilog and verilate detail.
To develop the Rocket-chip RTL, run:

```bash
# This command provide a environment that contains mill, circt, espresso... development tools.
nix develop '.#t1.elaborator'
```

> Metals LSP users are recommended to switch to mill-bsp mode instead of the default bloop mode.

To elaborate the RTLs, run mill or use the nix chroot:

```bash
# for development
mill -i elaborator.runMain org.chipsalliance.t1.elaborator.Main
# for clean build
nix build .#t1.rocketv-mlirbc
```

To develop the emulator, use the below nix environment:

```bash
nix develop .#t1.rocketv-emu.driver.devShell
```

This will setup the verilated C src in environment, download rust-analyzer.

```bash
cd rocketemu/driver
cargo build --release
```

#### Developing Testcases
The `tests/` contains the testcases. There are four types of testcases:

Expand Down
33 changes: 32 additions & 1 deletion build.sc
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ trait Chisel

object arithmetic extends Arithmetic

trait Arithmetic
trait Arithmetic
extends millbuild.dependencies.arithmetic.common.ArithmeticModule {
override def millSourcePath = os.pwd / "dependencies" / "arithmetic" / "arithmetic"
def scalaVersion = T(v.scala)
Expand Down Expand Up @@ -118,6 +118,23 @@ trait ConfigGen
def mainargsIvy = v.mainargs
}

object rocketv extends RocketV

trait RocketV
extends millbuild.common.RocketVModule
with ScalafmtModule {
def scalaVersion = T(v.scala)
def rvdecoderdbModule = rvdecoderdb
def riscvOpcodesPath = T.input(PathRef(os.pwd / "dependencies" / "riscv-opcodes"))
def hardfloatModule = hardfloat
def axi4Module = axi4

def chiselModule = Some(chisel)
def chiselPluginJar = T(Some(chisel.pluginModule.jar()))
def chiselPluginIvy = None
def chiselIvy = None
}

object ipemu extends IPEmulator

trait IPEmulator
Expand All @@ -132,6 +149,18 @@ trait IPEmulator
def chiselIvy = None
}

object rocketemu extends RocketEmulator
trait RocketEmulator extends millbuild.common.RocketEmulatorModule {
def scalaVersion = T(v.scala)

def rocketVModule = rocketv

def chiselModule = Some(chisel)
def chiselPluginJar = T(Some(chisel.pluginModule.jar()))
def chiselPluginIvy = None
def chiselIvy = None
}

object panamaconverter extends PanamaConverter

trait PanamaConverter
Expand All @@ -157,6 +186,8 @@ trait Elaborator
def generators = Seq(
t1,
ipemu,
rocketv,
rocketemu,
)

def mainargsIvy = v.mainargs
Expand Down
31 changes: 31 additions & 0 deletions common.sc
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,30 @@ trait ConfigGenModule
override def ivyDeps = T(super.ivyDeps() ++ Seq(mainargsIvy))
}

// T1 forked version of RocketCore
trait RocketModule
extends ScalaModule
with HasChisel
with HasRVDecoderDB {
def rocketchipModule: ScalaModule
def moduleDeps = super.moduleDeps ++ Seq(rocketchipModule)
}

// The next generation of purely standalone Rocket Core w/ AXI/CHI.
trait RocketVModule
extends ScalaModule
with HasChisel
with HasRVDecoderDB {
def axi4Module: ScalaModule
def hardfloatModule: ScalaModule

def moduleDeps = super.moduleDeps ++ Seq(axi4Module, hardfloatModule)
}

trait EmuHelperModule
extends ScalaModule
with HasChisel

trait IPEmulatorModule
extends ScalaModule
with HasChisel {
Expand Down Expand Up @@ -120,3 +144,10 @@ trait OMReaderModule
super.forkArgs() ++ Seq("--enable-native-access=ALL-UNNAMED", "--enable-preview", s"-Djava.library.path=${ circtInstallPath().path / "lib"}")
)
}

trait RocketEmulatorModule
extends ScalaModule
with HasChisel {
def rocketVModule: ScalaModule
def moduleDeps = super.moduleDeps ++ Seq(rocketVModule)
}
77 changes: 77 additions & 0 deletions elaborator/src/Elaborator.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2024 Jiuyang Liu <[email protected]>
package org.chipsalliance.t1.elaborator

import chisel3.RawModule
import chisel3.experimental.{SerializableModule, SerializableModuleGenerator, SerializableModuleParameter}
import mainargs.TokensReader

import scala.reflect.runtime.universe
import scala.reflect.runtime.universe.{runtimeMirror, typeOf}

// TODO: this will be upstreamed to Chisel
trait Elaborator {
implicit object PathRead extends TokensReader.Simple[os.Path] {
def shortName = "path"
def read(strs: Seq[String]) = Right(os.Path(strs.head, os.pwd))
}

def configImpl[P <: SerializableModuleParameter: universe.TypeTag](
parameter: P
)(implicit rwP: upickle.default.Writer[P]) = os.write.over(
os.pwd / s"${getClass.getSimpleName.replace("$", "")}.json",
upickle.default.write(parameter)
)

def designImpl[
M <: SerializableModule[P]: universe.TypeTag,
P <: SerializableModuleParameter: universe.TypeTag
](parameter: os.Path, runFirtool: Boolean)(implicit
rwP: upickle.default.Reader[P]
) = {
var fir: firrtl.ir.Circuit = null
val annos = Seq(
new chisel3.stage.phases.Elaborate,
new chisel3.stage.phases.Convert
).foldLeft(
Seq(
chisel3.stage.ChiselGeneratorAnnotation(() =>
SerializableModuleGenerator(
runtimeMirror(getClass.getClassLoader)
.runtimeClass(typeOf[M].typeSymbol.asClass)
.asInstanceOf[Class[M]],
upickle.default.read[P](os.read(parameter))
).module().asInstanceOf[RawModule]
)
): firrtl.AnnotationSeq
) { case (annos, stage) => stage.transform(annos) }
.flatMap {
case firrtl.stage.FirrtlCircuitAnnotation(circuit) =>
fir = circuit
None
case _: chisel3.stage.DesignAnnotation[_] => None
case _: chisel3.stage.ChiselCircuitAnnotation => None
case a => Some(a)
}
val annoJsonFile = os.pwd / s"${fir.main}.anno.json"
val firFile = os.pwd / s"${fir.main}.fir"
val svFile = os.pwd / s"${fir.main}.sv"
os.write.over(firFile, fir.serialize)
os.write.over(
annoJsonFile,
firrtl.annotations.JsonProtocol.serializeRecover(annos)
)
if (runFirtool) {
os.proc(
"firtool",
s"--annotation-file=${annoJsonFile}",
s"${firFile}",
s"-o",
s"${svFile}",
"--strip-debug-info",
"--verification-flavor=sva",
"--extract-test-code"
).call(os.pwd)
}
}
}
12 changes: 12 additions & 0 deletions elaborator/src/Main.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package org.chipsalliance.t1.elaborator

import mainargs._
import org.chipsalliance.t1.rtl.T1Parameter
import org.chipsalliance.rocketv.RocketTileParameter
import chisel3.panamalib.option._

object Main {
Expand Down Expand Up @@ -66,7 +67,15 @@ object Main {
def parameter: T1Parameter = generator.parameter
}

case class RocketConfig(
@arg(name = "rocket-config", short = 'c') rocketConfig: os.Path) {
def generator = upickle.default
.read[chisel3.experimental.SerializableModuleGenerator[org.chipsalliance.rocketv.RocketTile, org.chipsalliance.rocketv.RocketTileParameter]](ujson.read(os.read(rocketConfig)))
def parameter: RocketTileParameter = generator.parameter
}

implicit def ipConfig: ParserForClass[IPConfig] = ParserForClass[IPConfig]
implicit def rocketConfig: ParserForClass[RocketConfig] = ParserForClass[RocketConfig]

// format: off
@main def ip(elaborateConfig: ElaborateConfig, ipConfig: IPConfig): Unit = elaborateConfig.elaborate(() =>
Expand All @@ -75,6 +84,9 @@ object Main {
@main def ipemu(elaborateConfig: ElaborateConfig, ipConfig: IPConfig): Unit = elaborateConfig.elaborate(() =>
new org.chipsalliance.t1.ipemu.TestBench(ipConfig.generator)
)
@main def rocketemu(elaborateConfig: ElaborateConfig, rocketConfig: RocketConfig): Unit = elaborateConfig.elaborate(() =>
new org.chipsalliance.t1.rocketv.TestBench(rocketConfig.generator)
)
// format: on

def main(args: Array[String]): Unit = ParserForMethods(this).runOrExit(args)
Expand Down
26 changes: 26 additions & 0 deletions elaborator/src/rocketv/ALU.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2024 Jiuyang Liu <[email protected]>
package org.chipsalliance.t1.elaborator.rocketv

import mainargs._
import org.chipsalliance.rocketv.{ALU, ALUParameter}
import org.chipsalliance.t1.elaborator.Elaborator

object ALU extends Elaborator {
@main
case class ALUParameterMain(
@arg(name = "xLen") xLen: Int) {
def convert: ALUParameter = ALUParameter(xLen)
}

implicit def ALUParameterMainParser: ParserForClass[ALUParameterMain] = ParserForClass[ALUParameterMain]

@main
def config(@arg(name = "parameter") parameter: ALUParameterMain) = configImpl(parameter.convert)

@main
def design(@arg(name = "parameter") parameter: os.Path, @arg(name = "run-firtool") runFirtool: mainargs.Flag) =
designImpl[ALU, ALUParameter](parameter, runFirtool.value)

def main(args: Array[String]): Unit = ParserForMethods(this).runOrExit(args)
}
26 changes: 26 additions & 0 deletions elaborator/src/rocketv/AMOALU.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2024 Jiuyang Liu <[email protected]>
package org.chipsalliance.t1.elaborator.rocketv

import mainargs._
import org.chipsalliance.rocketv.{AMOALU, AMOALUParameter}
import org.chipsalliance.t1.elaborator.Elaborator

object AMOALU extends Elaborator {
@main
case class AMOALUParameterMain(
@arg(name = "operandBits") operandBits: Int) {
def convert: AMOALUParameter = AMOALUParameter(operandBits)
}

implicit def AMOALUParameterMainParser: ParserForClass[AMOALUParameterMain] = ParserForClass[AMOALUParameterMain]

@main
def config(@arg(name = "parameter") parameter: AMOALUParameterMain) = configImpl(parameter.convert)

@main
def design(@arg(name = "parameter") parameter: os.Path, @arg(name = "run-firtool") runFirtool: mainargs.Flag) =
designImpl[AMOALU, AMOALUParameter](parameter, runFirtool.value)

def main(args: Array[String]): Unit = ParserForMethods(this).runOrExit(args)
}
79 changes: 79 additions & 0 deletions elaborator/src/rocketv/BTB.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2024 Jiuyang Liu <[email protected]>
package org.chipsalliance.t1.elaborator.rocketv

import mainargs._
import org.chipsalliance.rocketv.{BHTParameter, BTB, BTBParameter}
import org.chipsalliance.t1.elaborator.Elaborator

object BTB extends Elaborator {
@main
case class BHTParameterMain(
@arg(name = "nEntries") nEntries: Int,
@arg(name = "counterLength") counterLength: Int,
@arg(name = "historyLength") historyLength: Int,
@arg(name = "historyBits") historyBits: Int) {
def convert: BHTParameter = BHTParameter(
nEntries,
counterLength,
historyLength,
historyBits
)
}
implicit def BHTParameterMainParser: ParserForClass[BHTParameterMain] = ParserForClass[BHTParameterMain]

@main
case class BTBParameterMain(
@arg(name = "useAsyncReset") useAsyncReset: Boolean,
@arg(name = "fetchBytes") fetchBytes: Int,
@arg(name = "vaddrBits") vaddrBits: Int,
@arg(name = "entries") entries: Int,
@arg(name = "nMatchBits") nMatchBits: Int,
@arg(name = "nPages") nPages: Int,
@arg(name = "nRAS") nRAS: Int,
@arg(name = "cacheBlockBytes") cacheBlockBytes: Int,
@arg(name = "iCacheSet") iCacheSet: Int,
@arg(name = "useCompressed") useCompressed: Boolean,
@arg(name = "updatesOutOfOrder") updatesOutOfOrder: Boolean,
@arg(name = "bht-nEntries") nEntries: Option[Int],
@arg(name = "bht-counterLength") counterLength: Option[Int],
@arg(name = "bht-historyLength") historyLength: Option[Int],
@arg(name = "bht-historyBits") historyBits: Option[Int],
@arg(name = "fetchWidth") fetchWidth: Int,
) {
def convert: BTBParameter = BTBParameter(
useAsyncReset,
fetchBytes,
vaddrBits,
entries,
nMatchBits,
nPages,
nRAS,
cacheBlockBytes,
iCacheSet,
useCompressed,
updatesOutOfOrder,
fetchWidth,
(nEntries
.lazyZip(counterLength)
.lazyZip(historyLength)
.lazyZip(historyBits))
.map {
case (nEntries, counterLength, historyLength, historyBits) =>
BHTParameter(nEntries, counterLength, historyLength, historyBits)
}
.headOption
)
}

implicit def BTBParameterMainParser: ParserForClass[BTBParameterMain] = ParserForClass[BTBParameterMain]

@main
def config(@arg(name = "parameter") parameter: BTBParameterMain) = configImpl(parameter.convert)

@main
def design(@arg(name = "parameter") parameter: os.Path, @arg(name = "run-firtool") runFirtool: mainargs.Flag) =
designImpl[BTB, BTBParameter](parameter, runFirtool.value)

def main(args: Array[String]): Unit = ParserForMethods(this).runOrExit(args)
}
Loading
Loading