Skip to content

Commit

Permalink
[nix] add derivation for vcs artifacts
Browse files Browse the repository at this point in the history
  • Loading branch information
Avimitin authored and sequencer committed Jul 31, 2024
1 parent fe6585b commit df37ae3
Show file tree
Hide file tree
Showing 5 changed files with 184 additions and 70 deletions.
8 changes: 5 additions & 3 deletions nix/t1/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,9 @@ lib.makeScope newScope
elaborateConfigJson = configPath;
elaborateConfig = builtins.fromJSON (lib.readFile configPath);

cases = innerSelf.callPackage ../../tests { verilator-emu = ip.verilator-emu; verilator-emu-trace = ip.verilator-emu-trace; };
cases = innerSelf.callPackage ../../tests {
inherit (ip) verilator-emu verilator-emu-trace vcs-emu vcs-emu-trace;
};

# for the convenience to use x86 cases on non-x86 machines, avoiding the extra build time
cases-x86 =
Expand Down Expand Up @@ -117,8 +119,8 @@ lib.makeScope newScope
};
vcs-dpi-lib = innerSelf.callPackage ../../difftest/online_vcs { };
vcs-dpi-lib-trace = vcs-dpi-lib.override { enable-trace = true; };
vcs-emu-compiled = innerSelf.callPackage ./vcs.nix { inherit vcs-dpi-lib; rtl = vcs-emu-rtl; };
vcs-emu-compiled-trace = innerSelf.callPackage ./vcs.nix { vcs-dpi-lib = vcs-dpi-lib-trace; rtl = vcs-emu-rtl; };
vcs-emu = innerSelf.callPackage ./vcs.nix { inherit vcs-dpi-lib; rtl = vcs-emu-rtl; };
vcs-emu-trace = innerSelf.callPackage ./vcs.nix { vcs-dpi-lib = vcs-dpi-lib-trace; rtl = vcs-emu-rtl; };
};

subsystem = rec {
Expand Down
1 change: 1 addition & 0 deletions nix/t1/vcs.nix
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ stdenv.mkDerivation {

passthru = {
inherit (vcs-dpi-lib) enable-trace;
inherit vcs-fhs-env;
};

shellHook = ''
Expand Down
112 changes: 61 additions & 51 deletions script/ci/src/Main.scala
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ object Main:
@main
def runTests(
jobs: String,
dontBail: Flag = Flag(false)
testType: String = "verilator"
): Unit =
if jobs == "" then
Logger.info("No test found, exiting")
Expand All @@ -157,32 +157,31 @@ object Main:
val Array(config, caseName) = testName.split(",")
println("\n")
Logger.info(
s"${BOLD}[${index + 1}/${allJobs.length}]${RESET} Running test case $caseName with config $config"
s"${BOLD}[${index + 1}/${allJobs.length}]${RESET} Running VCS for test case $caseName with config $config"
)

val testAttr = testType.toLowerCase() match
case "verilator" =>
s".#t1.$config.cases.$caseName.emu-result.with-offline"
case "vcs" => s".#t1.$config.cases.$caseName.emu-result.with-vcs"
case _ => Logger.fatal(s"Invalid test type ${testType}")
val testResultPath =
try
os.Path(
nixResolvePath(
s".#t1.$config.cases.$caseName.emu-result.with-offline"
testAttr,
if testType == "vcs" then Seq("--impure") else Seq()
)
)
catch
case _ =>
Logger.error(s"Emulation for config $config, case $caseName fail")
Logger.error(s"VCS emulation for config $config, case $caseName fail")
println("-" * 50)
println(
os.proc(
"nix",
"log",
s".#t1.$config.cases.$caseName.emu-result"
).call()
.out
)
println(os.proc("nix", "log", testAttr).call().out)
println("-" * 50)
Logger.fatal("Got error from emulation, exiting CI")

Logger.info("Checking RTL event with offline difftest")
Logger.info("Checking RTL event from VCS")
val testSuccess =
os.read(testResultPath / "offline-check-status").trim() == "0"
if !testSuccess then
Expand All @@ -193,10 +192,6 @@ object Main:

val failedTests = findFailedTests()
if failedTests.isEmpty then Logger.info(s"All tests passed")
else if dontBail.value then
Logger.error(
s"${BOLD}${failedTests.length} tests failed${RESET}"
)
else
Logger.fatal(
s"${BOLD}${failedTests.length} tests failed${RESET}"
Expand Down Expand Up @@ -249,13 +244,17 @@ object Main:
@arg(
name = "cycle-update-file-path",
doc = "specify the cycle update markdown file output path"
) cycleUpdateFilePath: String
) cycleUpdateFilePath: Option[String],
emuType: String = "verilator"
) =
val failedTestsFile = os.Path(failedTestsFilePath, os.pwd)
os.write.over(failedTestsFile, "## Failed Tests\n")

val cycleUpdateRecordFile = os.Path(cycleUpdateFilePath, os.pwd)
os.write.over(cycleUpdateRecordFile, "## Cycle Update\n")
if cycleUpdateFilePath.nonEmpty then
os.write.over(
os.Path(cycleUpdateFilePath.get, os.pwd),
"## Cycle Update\n"
)

os.walk(os.pwd / ".github" / "cases")
.filter(_.last == "default.json")
Expand All @@ -264,6 +263,11 @@ object Main:
var cycleRecord = ujson.read(os.read(file))

Logger.info("Fetching CI results")
val resultAttr = emuType.toLowerCase() match
case "verilator" =>
s".#t1.$config.cases._allEmuResult"
case "vcs" => s".#t1.$config.cases._allVCSEmuResult"
case _ => Logger.fatal(s"Invalid test type ${emuType}")
val emuResultPath =
os.Path(nixResolvePath(s".#t1.$config.cases._allEmuResult"))

Expand All @@ -278,30 +282,34 @@ object Main:
os.write.append(failedTestsFile, s"```text\n${journal}\n```\n")
})

Logger.info("Collecting cycle update info")
val perfCycleRegex = raw"total_cycles:\s(\d+)".r
val allCycleUpdates = os
.walk(emuResultPath)
.filter(path => path.last == "perf.txt")
.map(path => {
val cycle = os.read.lines(path).head match
case perfCycleRegex(cycle) => cycle.toInt
case _ =>
throw new Exception("perf.txt file is not format as expected")
val caseName = path.segments.toSeq.reverse.drop(1).head
(caseName, cycle, cycleRecord.obj(caseName).num.toInt)
})
.filter((_, newCycle, oldCycle) => newCycle != oldCycle)
.map:
case (caseName, newCycle, oldCycle) =>
cycleRecord(caseName) = newCycle
if oldCycle == -1 then s"* 🆕 ${caseName}($config): NaN -> ${newCycle}"
else if oldCycle > newCycle then
s"* 🚀 $caseName($config): $oldCycle -> $newCycle"
else s"* 🐢 $caseName($config): $oldCycle -> $newCycle"

os.write.append(cycleUpdateRecordFile, allCycleUpdates.mkString("\n"))
os.write.append(cycleUpdateRecordFile, "\n")
if cycleUpdateFilePath.nonEmpty then
Logger.info("Collecting cycle update info")
val perfCycleRegex = raw"total_cycles:\s(\d+)".r
val allCycleUpdates = os
.walk(emuResultPath)
.filter(path => path.last == "perf.txt")
.map(path => {
val cycle = os.read.lines(path).head match
case perfCycleRegex(cycle) => cycle.toInt
case _ =>
throw new Exception("perf.txt file is not format as expected")
val caseName = path.segments.toSeq.reverse.drop(1).head
(caseName, cycle, cycleRecord.obj(caseName).num.toInt)
})
.filter((_, newCycle, oldCycle) => newCycle != oldCycle)
.map:
case (caseName, newCycle, oldCycle) =>
cycleRecord(caseName) = newCycle
if oldCycle == -1 then
s"* 🆕 ${caseName}($config): NaN -> ${newCycle}"
else if oldCycle > newCycle then
s"* 🚀 $caseName($config): $oldCycle -> $newCycle"
else s"* 🐢 $caseName($config): $oldCycle -> $newCycle"

os.write.append(
os.Path(cycleUpdateFilePath.get, os.pwd),
allCycleUpdates.mkString("\n") + "\n"
)

os.write.over(file, ujson.write(cycleRecord, indent = 2))
end postCI
Expand All @@ -316,14 +324,16 @@ object Main:
println(ujson.write(Map("config" -> testPlans)))
end generateTestPlan

def nixResolvePath(attr: String): String =
def nixResolvePath(attr: String, extraArgs: Seq[String] = Seq()): String =
os.proc(
"nix",
"build",
"--no-link",
"--no-warn-dirty",
"--print-out-paths",
attr
Seq(
"nix",
"build",
"--no-link",
"--no-warn-dirty",
"--print-out-paths",
attr
) ++ extraArgs
).call()
.out
.trim()
Expand Down
27 changes: 23 additions & 4 deletions tests/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
, runCommand
, verilator-emu
, verilator-emu-trace
, vcs-emu
, vcs-emu-trace
}:

let
Expand All @@ -20,7 +22,7 @@ let
scope = lib.recurseIntoAttrs (lib.makeScope newScope (casesSelf: {
recurseForDerivations = true;

inherit verilator-emu verilator-emu-trace;
inherit xLen vLen isFp verilator-emu verilator-emu-trace vcs-emu vcs-emu-trace;

makeEmuResult = casesSelf.callPackage ./make-emu-result.nix { };

Expand Down Expand Up @@ -48,8 +50,6 @@ let

stdenv = rv32-stdenv;

inherit xLen vLen isFp;

mlir = casesSelf.callPackage ./mlir { };
intrinsic = casesSelf.callPackage ./intrinsic { };
asm = casesSelf.callPackage ./asm { };
Expand Down Expand Up @@ -88,6 +88,25 @@ let
in
runCommand "catch-${configName}-all-emu-result-for-ci" { } script;

_allVCSEmuResult =
let
testPlan = builtins.fromJSON (lib.readFile ../.github/cases/${configName}/default.json);
# flattern the attr set to a list of test case derivations
# AttrSet (AttrSet Derivation) -> List Derivation
allCases = lib.filter (val: lib.isDerivation val && lib.hasAttr val.pname testPlan)
(lib.concatLists (map lib.attrValues (lib.attrValues scopeStripped)));
script = ''
mkdir -p $out
'' + (lib.concatMapStringsSep "\n"
(caseDrv: ''
_caseOutDir=$out/${caseDrv.pname}
mkdir -p "$_caseOutDir"
cp ${caseDrv.emu-result.with-vcs}/offline-check-* "$_caseOutDir"/
'')
allCases);
in
runCommand "catch-${configName}-all-vcs-emu-result-for-ci" { } script;

all =
let
allCases = lib.filter lib.isDerivation
Expand All @@ -104,4 +123,4 @@ let
in
runCommand "build-all-testcases" { } script;
in
lib.recurseIntoAttrs (scopeStripped // { inherit all _allEmuResult; })
lib.recurseIntoAttrs (scopeStripped // { inherit all _allEmuResult _allVCSEmuResult; })
Loading

0 comments on commit df37ae3

Please sign in to comment.