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

Rocket cosim framework #3271

Closed
wants to merge 5 commits into from
Closed
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
587 changes: 587 additions & 0 deletions build.sc

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@
verilator cmake ninja
python3 python3Packages.bootstrapped-pip
pkgsCross.riscv64-embedded.buildPackages.gcc

libargs glog fmt zlib
gnused coreutils gnugrep which
parallel protobuf antlr4 numactl
Comment on lines +26 to +28
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only need to add necessary dependencies.


circt

spike riscvTests
Expand Down
49 changes: 48 additions & 1 deletion overlay.nix
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
final: prev: {
final: prev:
let
riscvTests = final.pkgsCross.riscv64-embedded.stdenv.mkDerivation rec {
pname = "riscv-tests";
version = "55bbcc8c06637a31cc01970881ba8072838a9121";
Expand All @@ -17,4 +18,50 @@ final: prev: {
];
buildPhase = "make RISCV_PREFIX=riscv64-none-elf-";
};

libspike = let
version = "1.1.0";
pname = "libspike";
cmakeConfig = ''
add_library(libspike STATIC IMPORTED GLOBAL)
set_target_properties(libspike PROPERTIES
IMPORTED_LOCATION "${placeholder "out"}/lib/libriscv.so")
target_include_directories(libspike INTERFACE
"${placeholder "out"}/include"
"${placeholder "out"}/include/riscv"
"${placeholder "out"}/include/fesvr"
"${placeholder "out"}/include/softfloat"
)
'';
in
final.stdenv.mkDerivation {
inherit version pname cmakeConfig;
enableParallelBuilding = true;
nativeBuildInputs = [ final.dtc ];
src = final.fetchFromGitHub {
owner = "riscv";
repo = "riscv-isa-sim";
rev = "ab3225a3ff687fda8b4180f9e4e0949a400d1247";
sha256 = "sha256-2cC2goTmxWnkTm3Tq08R8YkkuI2Fj8fRvpEPVZ5JvUI=";
};
configureFlags = [
"--enable-commitlog"
];
installPhase = ''
runHook preInstall
mkdir -p $out/include/{riscv,fesvr,softfloat} $out/lib $out/lib/cmake/libspike
cp riscv/*.h $out/include/riscv
cp fesvr/*.h $out/include/fesvr
cp softfloat/*.h $out/include/softfloat
cp config.h $out/include
cp *.so $out/lib
echo "$cmakeConfig" > $out/lib/cmake/libspike/libspike-config.cmake
runHook postInstall
'';
};
in
{
inherit libspike riscvTests;


}
9 changes: 9 additions & 0 deletions tests/cases/entrance/entrance.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.global _start
_start:
auipc t1, 0x0
addi a1, t1, 32
csrr a0, mhartid
lui t0, 0x80000
slli t0,t0,32
srli t0,t0,32
jr t0
19 changes: 19 additions & 0 deletions tests/cases/smoketest/smoke.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
.global _start
_start:
add t0,t0,x0
addi t0, x0, 0x1
addi t1, x0, 0x0
addi t3, x0, 0xa
loop:
add t1, t1, t0
add t0, t0, 0x1
add t3, t3, -1
bne t3, x0, loop
sd t1, 0x10(x0)
ld t2, 0x10(x0)
addi x20, x0, 0x1
addi x21, x0, 0x1
addi x22, x0, 0x1
addi x23, x0, 0x1
addi x24, x0, 0x1
addi x25, x0, 0x1
97 changes: 97 additions & 0 deletions tests/cosim/elaborate/src/DUT.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package tests.cosim.elabotate

import chisel3._
import freechips.rocketchip.diplomacy.{AddressSet, BundleBridgeSource, InModuleBody, LazyModule, RegionType, SimpleLazyModule, TransferSizes}
import freechips.rocketchip.interrupts.{IntSinkNode, IntSinkPortSimple, IntSourceNode, IntSourcePortSimple}
import freechips.rocketchip.subsystem._
import freechips.rocketchip.tilelink.{TLManagerNode, TLSlaveParameters, TLSlavePortParameters}
import org.chipsalliance.cde.config.Parameters
import freechips.rocketchip.tile.{NMI, PriorityMuxHartIdFromSeq, RocketTile}

import org.chipsalliance.cde.config.{Config, Field}

class DUT(p: Parameters) extends Module {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can directly use BaseSubsystem with InstantiatesTiles to construct a minimize version of LazyModule

implicit val implicitP = p
val tileParams = p(RocketTileParamsKey)
val ldut = LazyModule(new SimpleLazyModule {
implicit val implicitP = p
val rocketTile = LazyModule(new RocketTile(tileParams, RocketCrossingParams(), PriorityMuxHartIdFromSeq(Seq(tileParams))))
val masterNode = TLManagerNode(Seq(TLSlavePortParameters.v1(
Seq(TLSlaveParameters.v1(
address = List(AddressSet(0x0, 0xffffffffL)),
regionType = RegionType.UNCACHED,
executable = true,
supportsGet = TransferSizes(1, 64),
supportsAcquireT = TransferSizes(1, 64),
supportsAcquireB = TransferSizes(1, 64),
supportsPutPartial = TransferSizes(1, 64),
supportsPutFull = TransferSizes(1, 64),
supportsLogical = TransferSizes(1, 64),
supportsArithmetic = TransferSizes(1, 64),
fifoId = Some(0))),
beatBytes = 8,
endSinkId = 4,
minLatency = 1
)))
masterNode :=* rocketTile.masterNode
val memory = InModuleBody {
masterNode.makeIOs()
}

val intNode = IntSourceNode(IntSourcePortSimple())
rocketTile.intInwardNode :=* intNode
val intIn = InModuleBody {
intNode.makeIOs()
}

val haltNode = IntSinkNode(IntSinkPortSimple())
haltNode :=* rocketTile.haltNode
val haltOut = InModuleBody {
haltNode.makeIOs()
}

val ceaseNode = IntSinkNode(IntSinkPortSimple())
ceaseNode :=* rocketTile.ceaseNode
val ceaseOut = InModuleBody {
ceaseNode.makeIOs()
}

val wfiNode = IntSinkNode(IntSinkPortSimple())
wfiNode :=* rocketTile.wfiNode
val wfiOut = InModuleBody {
wfiNode.makeIOs()
}
val resetVectorNode = BundleBridgeSource(() => UInt(32.W))
rocketTile.resetVectorNode := resetVectorNode
val resetVector = InModuleBody {
resetVectorNode.makeIO()
}
val hartidNode = BundleBridgeSource(() => UInt(4.W))
rocketTile.hartIdNode := hartidNode
InModuleBody {
hartidNode.bundle := 0.U
}
val nmiNode = BundleBridgeSource(Some(() => new NMI(32)))
rocketTile.nmiNode := nmiNode
val nmi = InModuleBody {
nmiNode.makeIO()
}
Comment on lines +19 to +78
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These logic is already implemented in the InstantiatesTiles, please use it.

})
chisel3.experimental.DataMirror.fullModulePorts(
// instantiate the LazyModule
Module(ldut.module)
).filterNot(_._2.isInstanceOf[Aggregate]).foreach { case (name, ele) =>
if (!(name == "clock" || name == "reset")) {
chisel3.experimental.DataMirror.directionOf(ele) match {
case ActualDirection.Output =>
val io = IO(Output(chiselTypeOf(ele))).suggestName(name)
println(s"output $name")
io := ele
case ActualDirection.Input =>
val io = IO(Input(chiselTypeOf(ele))).suggestName(name)
println(s"input $name")
ele := io
}
}
}
Comment on lines +80 to +96
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIRC this hack should be fixed.

}
94 changes: 94 additions & 0 deletions tests/cosim/elaborate/src/Main.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package tests.cosim.elabotate


import chisel3.aop.Select
import chisel3.aop.injecting.InjectingAspect
import chisel3.stage.ChiselGeneratorAnnotation
import circt.stage.{CIRCTTarget, CIRCTTargetAnnotation, ChiselStage, FirtoolOption}
import firrtl.options.TargetDirAnnotation
import firrtl.{AnnotationSeq, ChirrtlEmitter, EmitAllModulesAnnotation}
import freechips.rocketchip.devices.debug.DebugModuleKey
import freechips.rocketchip.diplomacy.MonitorsEnabled
import freechips.rocketchip.subsystem.{CacheBlockBytes, SystemBusKey, SystemBusParams}
import mainargs._
import org.chipsalliance.cde.config.{Config, Field}
import freechips.rocketchip.rocket.{DCacheParams, FrontendModule, ICacheModule, ICacheParams, MulDivParams, Rocket, RocketCoreParams}
import freechips.rocketchip.tile.RocketTileParams

import freechips.rocketchip.system._
import chisel3.stage.{ChiselCli, ChiselStage}
import firrtl.AnnotationSeq
import firrtl.options.PhaseManager.PhaseDependency
import firrtl.options.{Dependency, Phase, PhaseManager, PreservesAll, Shell, Stage, StageMain}
import firrtl.stage.FirrtlCli
import freechips.rocketchip.stage.RocketChipCli

import scala.collection.immutable.Seq

/** Modified ChiselStage that includes the GenerateROMs phase */
private[freechips] final class RocketChiselStage extends ChiselStage {

override val targets = Seq(
Dependency[chisel3.stage.phases.Checks],
Dependency[chisel3.stage.phases.Elaborate],
Dependency[freechips.rocketchip.stage.phases.GenerateROMs],
Dependency[chisel3.stage.phases.AddImplicitOutputFile],
Dependency[chisel3.stage.phases.AddImplicitOutputAnnotationFile],
Dependency[chisel3.stage.phases.MaybeAspectPhase],
Dependency[chisel3.stage.phases.Emitter],
Dependency[chisel3.stage.phases.Convert]
)

}

class RocketChipStage extends Stage with PreservesAll[Phase] {

override val shell = new Shell("rocket-chip") with RocketChipCli with ChiselCli with FirrtlCli
val targets: Seq[PhaseDependency] = Seq(
Dependency[freechips.rocketchip.stage.phases.Checks],
Dependency[freechips.rocketchip.stage.phases.TransformAnnotations],
Dependency[freechips.rocketchip.stage.phases.PreElaboration],
Dependency[RocketChiselStage],
Dependency[freechips.rocketchip.stage.phases.GenerateFirrtlAnnos],
Dependency[freechips.rocketchip.stage.phases.AddDefaultTests],
Dependency[freechips.rocketchip.stage.phases.GenerateTestSuiteMakefrags],
Dependency[freechips.rocketchip.stage.phases.GenerateArtefacts]
)

private val pm = new PhaseManager(targets)

override def run(annotations: AnnotationSeq): AnnotationSeq = pm.transform(annotations)

}

object Generator extends StageMain(new RocketChipStage)
Comment on lines +29 to +64
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't use RC Stage here.
I draft a minimized Main object here, I will find some time to finish it.



object RocketTileParamsKey extends Field[RocketTileParams]

class cosimConfig extends Config((site, here, up) => {
case MonitorsEnabled => false
case freechips.rocketchip.tile.XLen => 64
case freechips.rocketchip.tile.XLen => 64
case freechips.rocketchip.tile.MaxHartIdBits => 4
case freechips.rocketchip.tile.MaxHartIdBits => 4
case freechips.rocketchip.rocket.PgLevels => if (site(freechips.rocketchip.tile.XLen) == 64) 3 else 2
case freechips.rocketchip.rocket.PgLevels => if (site(freechips.rocketchip.tile.XLen) == 64) 3 else 2
case RocketTileParamsKey => RocketTileParams(
core = RocketCoreParams(mulDiv = Some(MulDivParams(
mulUnroll = 8,
mulEarlyOut = true,
divEarlyOut = true))),
dcache = Some(DCacheParams(
rowBits = site(SystemBusKey).beatBits,
nMSHRs = 0,
blockBytes = site(CacheBlockBytes))),
icache = Some(ICacheParams(
rowBits = site(SystemBusKey).beatBits,
blockBytes = site(CacheBlockBytes))))
case SystemBusKey => SystemBusParams(
beatBytes = site(freechips.rocketchip.tile.XLen) / 8,
blockBytes = site(CacheBlockBytes))
case DebugModuleKey => None
})
Comment on lines +69 to +93
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should be able to use RC default configs.


17 changes: 17 additions & 0 deletions tests/cosim/emulator/src/exceptions.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#pragma once

#include <stdexcept>

class CosimException : public std::runtime_error {
public:
explicit CosimException(const char *what) : runtime_error(what) {}
};

class TimeoutException : CosimException {
public:
TimeoutException() : CosimException("timeout") {}
};

#define CHECK_S(condition) \
LOG_IF(FATAL_S, GOOGLE_PREDICT_BRANCH_NOT_TAKEN(!(condition))) \
<< "Check failed: " #condition " "
35 changes: 35 additions & 0 deletions tests/cosim/emulator/src/glog_exception_safe.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#pragma once

#include <glog/logging.h>

namespace google {

class CheckFailedException : public std::runtime_error {
public:
explicit CheckFailedException() : std::runtime_error("check failed") {}
};

class LogMessageFatal_S : public LogMessage {
public:
LogMessageFatal_S(const char *file, int line) : LogMessage(file, line, GLOG_ERROR){};
LogMessageFatal_S(const char *file, int line, const CheckOpString &result) : LogMessage(file, line, GLOG_ERROR) {
stream() << "Check failed: " << (*result.str_) << " ";
};
~LogMessageFatal_S() noexcept(false) {
Flush();
throw CheckFailedException();
};
};
}// namespace google

#define CHECK_OP_S(name, op, val1, val2) \
CHECK_OP_LOG(name, op, val1, val2, google::LogMessageFatal_S)

#define COMPACT_GOOGLE_LOG_FATAL_S google::LogMessageFatal_S(__FILE__, __LINE__)

#define CHECK_EQ_S(val1, val2) CHECK_OP_S(_EQ, ==, val1, val2)
#define CHECK_NE_S(val1, val2) CHECK_OP_S(_NE, !=, val1, val2)
#define CHECK_LE_S(val1, val2) CHECK_OP_S(_LE, <=, val1, val2)
#define CHECK_LT_S(val1, val2) CHECK_OP_S(_LT, <, val1, val2)
#define CHECK_GE_S(val1, val2) CHECK_OP_S(_GE, >=, val1, val2)
#define CHECK_GT_S(val1, val2) CHECK_OP_S(_GT, >, val1, val2)
32 changes: 32 additions & 0 deletions tests/cosim/emulator/src/main.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#include <args.hxx>
#include <fmt/core.h>
#include <glog/logging.h>

#include "exceptions.h"
#include "glog_exception_safe.h"
#include "vbridge.h"

int main(int argc, char **argv) {
FLAGS_logtostderr = 1;
google::InitGoogleLogging(argv[0]);
google::InstallFailureSignalHandler();

args::ArgumentParser parser("Rocket");
args::ValueFlag<std::string> bin(parser, "bin", "test case path", {"bin"});
args::ValueFlag<std::string> entrance(parser, "entrance", "entrance", {"entrance"});
args::ValueFlag<std::string> wave(parser, "wave", "wave output path(in fst)", {"wave"});
args::ValueFlag<uint64_t> reset_vector(parser, "reset_vector", "set reset vector", {"reset-vector"}, 0x80000000);
args::ValueFlag<uint64_t> cycles(parser, "cycles", "set simulation cycles", {"cycles"}, 1000);
parser.ParseCLI(argc, argv);

try {
VBridge vb;
vb.configure_simulator(argc, argv);
vb.setup(bin.Get(), entrance.Get(), wave.Get() + ".fst", reset_vector.Get(), cycles.Get());
vb.loop();
} catch (TimeoutException &e) {
return 0;
} catch (google::CheckFailedException &e) {
return 1;
}
}
Loading