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 Coverage flow for t1 #790

Merged
merged 5 commits into from
Oct 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 3 additions & 0 deletions .github/workflows/vcs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,12 @@ jobs:
- name: "Print step summary"
run: |
nix run ".#ci-helper" -- postCI \
--urg-report-file-path ./urg-report.md \
--cycle-update-file-path ./cycle-update.md \
--failed-tests-file-path ./failed-tests.md \
--emu-type vcs
cat ./urg-report.md >> $GITHUB_STEP_SUMMARY
echo >> $GITHUB_STEP_SUMMARY
cat ./cycle-update.md >> $GITHUB_STEP_SUMMARY
echo >> $GITHUB_STEP_SUMMARY
cat ./failed-tests.md >> $GITHUB_STEP_SUMMARY
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,8 @@ $ nix build .#t1.elaborator # the wrapped jar file of the Chisel elaborator
$ nix build .#t1.<config-name>.ip.rtl # the elaborated IP core .sv files
$ nix build .#t1.<config-name>.ip.emu-rtl # the elaborated IP core .sv files with emulation support
$ nix build .#t1.<config-name>.ip.verilator-emu # build the IP core emulator using verilator
$ nix build .#t1.<config-name>.ip.vcs-emu # build the IP core emulator using VCS
$ nix build .#t1.<config-name>.ip.vcs-emu-trace # build the IP core emulator using VCS w/ trace support
$ nix build .#t1.<config-name>.ip.vcs-emu --impure # build the IP core emulator using VCS w/ VCS environment locally
$ nix build .#t1.<config-name>.ip.vcs-emu-trace --impure # build the IP core emulator using VCS w/ trace support

$ nix build .#t1.<config-name>.subsystem.rtl # the elaborated soc .sv files
$ nix build .#t1.<config-name>.subsystem.emu-rtl # the elaborated soc .sv files with emulation support
Expand Down
19 changes: 18 additions & 1 deletion nix/t1/conversion/sv-to-vcs-simulator.nix
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ stdenv.mkDerivation rec {
# require license
__noChroot = true;
dontPatchELF = true;
enableCover = true;

src = rtl;

Expand All @@ -31,10 +32,18 @@ stdenv.mkDerivation rec {
"-file"
"filelist.f"
]
++ lib.optionals (enableCover) [
"-cm"
"line+cond+fsm+tgl+branch+assert"
"-cm_dir"
"./cm"
]
++ lib.optionals (enableTrace) [
"+define+T1_ENABLE_TRACE"
"-debug_access+pp+dmptf+thread"
"-kdb=common_elab,hgldd_all"
"-assert"
"disable_cover"
]
++ vcsLinkLibs;

Expand Down Expand Up @@ -65,13 +74,21 @@ stdenv.mkDerivation rec {
mkdir -p $out/bin $out/lib
cp $mainProgram $out/lib
cp -r $mainProgram.daidir $out/lib
${lib.optionalString enableCover ''
cp -r ./cm.vdb $out/lib
''}

# We need to carefully handle string escape here, so don't use makeWrapper
tee $out/bin/$mainProgram <<EOF
#!${bash}/bin/bash
export LD_LIBRARY_PATH="$out/lib/$mainProgram.daidir:\$LD_LIBRARY_PATH"
_argv="\$@"
${vcs-fhs-env}/bin/vcs-fhs-env -c "$out/lib/$mainProgram \$_argv"

${lib.optionalString enableCover ''
cp -r $out/lib/cm.vdb ./cm.vdb
chmod +w -R ./cm.vdb
''}
${vcs-fhs-env}/bin/vcs-fhs-env -c "$out/lib/$mainProgram ${lib.optionalString enableCover ''-cm_dir ./cm.vdb''} \$_argv"
EOF
chmod +x $out/bin/$mainProgram

Expand Down
14 changes: 13 additions & 1 deletion nix/t1/run/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,21 @@ let
fi

cp -v ${caseDrv}/offline-check-* "$_caseOutDir"/

if [ -d ${caseDrv}/cm.vdb ]; then
cp -vr ${caseDrv}/cm.vdb "$_caseOutDir"/
fi
'')
allCasesResult);
in
runCommand "catch-${configName}-all-emu-result-for-ci" { } script;

_vcsEmuResult = runCommand "get-vcs-emu-result" { __noChroot = true; emuOutput = _getAllResult "vcs-emu"; } ''
cp -vr $emuOutput $out
chmod -R u+w $out

${vcs-emu.vcs-fhs-env}/bin/vcs-fhs-env -c "urg -dir $emuOutput/*/cm.vdb -format text"
cp -vr urgReport $out/
'';
in
emuAttrs // { _vcsEmuResult = _getAllResult "vcs-emu"; }
emuAttrs // { inherit _vcsEmuResult; }
4 changes: 4 additions & 0 deletions nix/t1/run/run-vcs-emu.nix
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ stdenvNoCC.mkDerivation (finalAttr: {
emuDriverArgsArray=(
"+t1_elf_file=${testCase}/bin/${testCase.pname}.elf"
${lib.optionalString emulator.enableTrace "+t1_wave_path=${testCase.pname}.fsdb"}
"-cm assert"
)
emuDriverArgs="''${emuDriverArgsArray[@]}"
emuDriver="${emulator}/bin/${emulator.mainProgram}"
Expand Down Expand Up @@ -78,6 +79,9 @@ stdenvNoCC.mkDerivation (finalAttr: {
mv perf.json $out/
fi

cp -v cm.log "$out"
cp -vr cm.vdb "$out"

${lib.optionalString emulator.enableTrace ''
cp -v ${testCase.pname}.fsdb "$out"
cp -vr ${emulator}/lib/${emulator.mainProgram}.daidir "$out"
Expand Down
24 changes: 24 additions & 0 deletions script/ci/src/Main.scala
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,10 @@ object Main:
name = "cycle-update-file-path",
doc = "specify the cycle update markdown file output path"
) cycleUpdateFilePath: String,
@arg(
name = "urg-report-file-path",
doc = "specify the urg report markdown file output path"
) urgReportFilePath: Option[String],
@arg(
name = "emu-type",
doc = "Specify emulation type"
Expand All @@ -231,6 +235,9 @@ object Main:
"## Cycle Update\n"
)

if urgReportFilePath.nonEmpty then
os.write(os.Path(urgReportFilePath.get, os.pwd), "# Coverage report\n")

os.walk(os.pwd / ".github" / caseDir)
.filter(_.last == "default.json")
.foreach: file =>
Expand Down Expand Up @@ -281,6 +288,23 @@ object Main:
allCycleUpdates.mkString("\n") + "\n"
)

if urgReportFilePath.nonEmpty then
Logger.info("Filtering urg report")
val finalMdPath = os.Path(urgReportFilePath.get, os.pwd)
val urgAssertFile = emuResultPath / "urgReport" / "asserts.txt"
val heading = "^Summary for Cover Properties$".r
val coverSummaryStr =
os.read(urgAssertFile)
.lines()
.dropWhile(!heading.matches(_))
.takeWhile(_.distinct != "-")
.toArray
.mkString("\n")
os.write.append(finalMdPath, s"### Coverage for $config \n")
os.write.append(finalMdPath, "```text\n")
os.write.append(finalMdPath, coverSummaryStr)
os.write.append(finalMdPath, "\n```\n")

os.write.over(file, ujson.write(cycleRecord, indent = 2))
end postCI

Expand Down
12 changes: 11 additions & 1 deletion script/emu/src/Main.scala
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,8 @@ object Main:
s"No cached emulator selection nor --emu argument was provided"
)

val isTrace = finalEmuType.get.endsWith("-trace")
val isTrace = finalEmuType.get.contains("-trace")
val isCover = true

val finalConfig = tryRestoreFromCache("config", config)
if finalConfig.isEmpty then
Expand All @@ -204,6 +205,7 @@ object Main:
s"+t1_elf_file=${caseElfPath}"
)
++ optionals(isTrace, Seq(s"+t1_wave_path=${outputPath / "wave.fsdb"}"))
++ optionals(isCover, Seq(s"-cm assert"))
++ optionals(!leftOverArguments.isEmpty, leftOverArguments)

if dryRun.value then return
Expand Down Expand Up @@ -259,6 +261,14 @@ object Main:

Logger.info("Driver finished")

if isCover then
if os.exists(os.pwd / "cm.vdb") && os.exists(os.pwd / "cm.log") then
os.move(os.pwd / "cm.vdb", outputPath / "cm.vdb", replaceExisting = true)
os.move(os.pwd / "cm.log", outputPath / "cm.log", replaceExisting = true)
Logger.info(s"Coverage database saved under ${outputPath}/cm.vdb")
else
Logger.error("No cm.vdb cm.log found")

if os.exists(os.pwd / "perf.json") then
os.move(os.pwd / "perf.json", outputPath / "perf.json", replaceExisting = true)

Expand Down
8 changes: 7 additions & 1 deletion t1emu/src/TestBench.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@ import chisel3.util.circt.dpi.{
RawClockedVoidFunctionCall,
RawUnclockedNonVoidFunctionCall
}
import chisel3.util.{HasExtModuleInline, PopCount, UIntToOH, Valid}
import chisel3.util.{BitPat, HasExtModuleInline, PopCount, UIntToOH, Valid}
import chisel3.ltl.{CoverProperty, Sequence}
import org.chipsalliance.amba.axi4.bundle._
import org.chipsalliance.t1.t1emu.dpi._
import org.chipsalliance.t1.rtl.{T1, T1Parameter}
import org.chipsalliance.rvdecoderdb.Instruction

@instantiable
class TestBenchOM extends Class {
Expand Down Expand Up @@ -283,4 +285,8 @@ class TestBench(generator: SerializableModuleGenerator[T1, T1Parameter])
scoreboard.bits := 0.U
}
}
generator.parameter.decoderParam.allInstructions.map { instruction: Instruction =>
val issueMatch = Sequence.BoolSequence(issue.instruction === BitPat("b" + instruction.encoding.toString))
CoverProperty(issueMatch, label = Some(s"t1_cover_issue_${instruction.name}"))
}
}