diff --git a/build.sbt b/build.sbt index c4197aba77..f19038ec59 100644 --- a/build.sbt +++ b/build.sbt @@ -173,7 +173,7 @@ lazy val chipyard = { Seq( testchipip, rocketchip, boom, rocketchip_blocks, rocketchip_inclusive_cache, icenet, tracegen, - constellation, barf, shuttle, rerocc, + constellation, barf, shuttle, rerocc, tacit, ).map(sbt.Project.projectToRef) ++ (if (useChisel7) Seq() else Seq(sbt.Project.projectToRef(firrtl2_bridge))) ++ (if (useChisel7) Seq() else Seq(sbt.Project.projectToRef(dsptools), sbt.Project.projectToRef(rocket_dsp_utils))) diff --git a/generators/chipyard/src/main/scala/DigitalTop.scala b/generators/chipyard/src/main/scala/DigitalTop.scala index ef1882bf9a..5ad9ca84cb 100644 --- a/generators/chipyard/src/main/scala/DigitalTop.scala +++ b/generators/chipyard/src/main/scala/DigitalTop.scala @@ -14,6 +14,7 @@ import freechips.rocketchip.devices.tilelink._ // DOC include start: DigitalTop class DigitalTop(implicit p: Parameters) extends ChipyardSystem + with tacit.CanHaveTraceSinkRawByte // Enables optionally adding the trace sink raw byte with testchipip.tsi.CanHavePeripheryUARTTSI // Enables optional UART-based TSI transport with testchipip.boot.CanHavePeripheryCustomBootPin // Enables optional custom boot pin with testchipip.cosim.CanHaveTraceIO // Enables optionally adding trace IO diff --git a/generators/chipyard/src/main/scala/config/AbstractConfig.scala b/generators/chipyard/src/main/scala/config/AbstractConfig.scala index 490b8ebca9..8dad151846 100644 --- a/generators/chipyard/src/main/scala/config/AbstractConfig.scala +++ b/generators/chipyard/src/main/scala/config/AbstractConfig.scala @@ -15,6 +15,7 @@ class AbstractConfig extends Config( // Set up TestHarness // ================================================ // The HarnessBinders control generation of hardware in the TestHarness + new chipyard.harness.WithTraceSinkRawByteHarnessTieOff ++ /** tie-off trace-sink-raw-byte port, if present */ new chipyard.harness.WithUARTAdapter ++ /** add UART adapter to display UART on stdout, if uart is present */ new chipyard.harness.WithBlackBoxSimMem ++ /** add SimDRAM DRAM model for axi4 backing memory, if axi4 mem is enabled */ new chipyard.harness.WithSimTSIOverSerialTL ++ /** add external serial-adapter and RAM */ @@ -62,6 +63,7 @@ class AbstractConfig extends Config( new chipyard.iobinders.WithTraceIOPunchthrough ++ new chipyard.iobinders.WithUARTTSIPunchthrough ++ new chipyard.iobinders.WithGCDIOPunchthrough ++ + new chipyard.iobinders.WithTraceSinkRawBytePunchthrough ++ new chipyard.iobinders.WithNMITiedOff ++ new chipyard.iobinders.WithOffchipBusSel ++ diff --git a/generators/chipyard/src/main/scala/config/fragments/TileFragments.scala b/generators/chipyard/src/main/scala/config/fragments/TileFragments.scala index da36e52bbe..4b37a76fb4 100644 --- a/generators/chipyard/src/main/scala/config/fragments/TileFragments.scala +++ b/generators/chipyard/src/main/scala/config/fragments/TileFragments.scala @@ -170,3 +170,14 @@ class WithSV48 extends Config((site, here, up) => { tp.tileParams.core.copy(pgLevels = 4))) } }) + +class WithAsidLen(n: Int = 0) extends Config((site, here, up) => { + case TilesLocated(InSubsystem) => up(TilesLocated(InSubsystem), site) map { + case tp: RocketTileAttachParams => tp.copy(tileParams = tp.tileParams.copy(core = + tp.tileParams.core.copy(asidLen = n))) + // case tp: boom.v3.common.BoomTileAttachParams => tp.copy(tileParams = tp.tileParams.copy(core = + // tp.tileParams.core.copy(nAsidBits = n))) + // case tp: boom.v4.common.BoomTileAttachParams => tp.copy(tileParams = tp.tileParams.copy(core = + // tp.tileParams.core.copy(nAsidBits = n))) + } +}) \ No newline at end of file diff --git a/generators/chipyard/src/main/scala/harness/HarnessBinders.scala b/generators/chipyard/src/main/scala/harness/HarnessBinders.scala index 0ba96dbccb..14d83ede07 100644 --- a/generators/chipyard/src/main/scala/harness/HarnessBinders.scala +++ b/generators/chipyard/src/main/scala/harness/HarnessBinders.scala @@ -334,6 +334,12 @@ class WithResetFromHarness extends HarnessBinder({ } }) +class WithTraceSinkRawByteHarnessTieOff extends HarnessBinder({ + case (th: HasHarnessInstantiators, port: TraceSinkRawBytePort, chipId: Int) => { + port.io.out.ready := false.B + } +}) + class WithOffchipBusSelPlusArg extends HarnessBinder({ case (th: HasHarnessInstantiators, port: OffchipSelPort, chipId: Int) => { val pin = PlusArg("offchip_sel", width=port.io.getWidth) diff --git a/generators/chipyard/src/main/scala/iobinders/IOBinders.scala b/generators/chipyard/src/main/scala/iobinders/IOBinders.scala index a923247617..b5629001e9 100644 --- a/generators/chipyard/src/main/scala/iobinders/IOBinders.scala +++ b/generators/chipyard/src/main/scala/iobinders/IOBinders.scala @@ -40,6 +40,7 @@ import testchipip.tsi.{CanHavePeripheryUARTTSI, UARTTSIIO} import icenet.{CanHavePeripheryIceNIC, SimNetwork, NicLoopback, NICKey, NICIOvonly} import chipyard.{CanHaveMasterTLMemPort, ChipyardSystem, ChipyardSystemModule} import chipyard.example.{CanHavePeripheryGCD} +import tacit.{CanHaveTraceSinkRawByte, TraceSinkRawByteBundle} import scala.reflect.{ClassTag} @@ -598,6 +599,18 @@ class WithGCDIOPunchthrough extends OverrideIOBinder({ } }) +class WithTraceSinkRawBytePunchthrough extends OverrideIOBinder({ + (system: CanHaveTraceSinkRawByte) => { + val tacit_byte_ports = system.tacit_bytes.zipWithIndex.map { case (s, i) => + // a seq of decoupled bytes + val tacit_byte = IO(new TraceSinkRawByteBundle).suggestName(s"tacit_byte_${i}") + tacit_byte <> s + TraceSinkRawBytePort(() => tacit_byte) + } + (tacit_byte_ports, Nil) + } +}) + class WithOffchipBusSel extends OverrideIOBinder({ (system: CanHaveSwitchableOffchipBus) => { system.io_obus_sel.getWrappedValue.map { sel => diff --git a/generators/chipyard/src/main/scala/iobinders/Ports.scala b/generators/chipyard/src/main/scala/iobinders/Ports.scala index 93c95416f9..c5b4e32087 100644 --- a/generators/chipyard/src/main/scala/iobinders/Ports.scala +++ b/generators/chipyard/src/main/scala/iobinders/Ports.scala @@ -18,6 +18,7 @@ import freechips.rocketchip.subsystem.{MemoryPortParams, MasterPortParams, Slave import freechips.rocketchip.devices.debug.{ClockedDMIIO} import freechips.rocketchip.tilelink.{TLBundle} import org.chipsalliance.diplomacy.nodes.{HeterogeneousBag} +import tacit.TraceSinkRawByteBundle trait Port[T <: Data] { val getIO: () => T @@ -112,6 +113,9 @@ case class TLMemPort (val getIO: () => HeterogeneousBag[TLBundle]) case class GCDBusyPort (val getIO: () => Bool) extends Port[Bool] +case class TraceSinkRawBytePort(val getIO: () => TraceSinkRawByteBundle) + extends Port[TraceSinkRawByteBundle] + case class OffchipSelPort (val getIO: () => UInt) extends Port[UInt] diff --git a/generators/firechip/bridgeinterfaces/src/main/scala/TraceRawByte.scala b/generators/firechip/bridgeinterfaces/src/main/scala/TraceRawByte.scala new file mode 100644 index 0000000000..c79881720b --- /dev/null +++ b/generators/firechip/bridgeinterfaces/src/main/scala/TraceRawByte.scala @@ -0,0 +1,16 @@ +package firechip.bridgeinterfaces + +import chisel3._ +import chisel3.util._ + +class TraceRawBytePortIO extends Bundle { + val out = Decoupled(UInt(8.W)) +} + +class TraceRawByteBridgeTargetIO extends Bundle { + val byte = Flipped(new TraceRawBytePortIO) + val reset = Input(Bool()) + val clock = Input(Clock()) +} + +case class TraceRawByteKey() // intentionally empty \ No newline at end of file diff --git a/generators/firechip/bridgestubs/src/main/cc/bridges/tacit.cc b/generators/firechip/bridgestubs/src/main/cc/bridges/tacit.cc new file mode 100644 index 0000000000..cce575aa41 --- /dev/null +++ b/generators/firechip/bridgestubs/src/main/cc/bridges/tacit.cc @@ -0,0 +1,152 @@ +// See LICENSE for license details + +#include "tacit.h" +#include "core/simif.h" + +#include +#include + +#include +#include +#include +#include +#include +#include + +// #define DEBUG + +char tacit_t::KIND; + +class tacit_handler_impl final : public tacit_handler { +public: + tacit_handler_impl(int tacitno, int tacitlogfd); + ~tacit_handler_impl() override; + +protected: + int tacitlogfd; + static constexpr size_t BUFFER_SIZE = 4096; + std::array buffer{}; + size_t buffered_bytes = 0; + + void put(uint8_t data) override; + void flush_buffer(); +}; + +static void fatal_io_error(int fd, const char *operation) { + fprintf(stderr, + "TACIT log fd %d: failed to %s: %s\n", + fd, + operation, + strerror(errno)); + abort(); +} + +tacit_handler_impl::tacit_handler_impl(int tacitno, int tacitlogfd) { + (void)tacitno; + this->tacitlogfd = tacitlogfd; +} + +tacit_handler_impl::~tacit_handler_impl() { + if (buffered_bytes) { + flush_buffer(); + } + while (::close(tacitlogfd) == -1) { + if (errno == EINTR) { + continue; + } + fatal_io_error(tacitlogfd, "close"); + } +} + +void tacit_handler_impl::put(uint8_t data) { + buffer[buffered_bytes++] = data; + if (buffered_bytes == BUFFER_SIZE) { + flush_buffer(); + } + #ifdef DEBUG + fprintf(stderr, "TACIT%d: %02x\n", tacitlogfd, data); + #endif +} + +void tacit_handler_impl::flush_buffer() { + size_t offset = 0; + while (offset < buffered_bytes) { + ssize_t bytes_written = + ::write(tacitlogfd, buffer.data() + offset, buffered_bytes - offset); + if (bytes_written > 0) { + offset += static_cast(bytes_written); + continue; + } + if (bytes_written == -1 && errno == EINTR) { + continue; + } + fatal_io_error(tacitlogfd, "write"); + } + buffered_bytes = 0; +} + +static std::unique_ptr +create_handler(const std::vector &args, int tacitno) { + // open a new file for dumping the bytes + std::string tacitlogname = std::string("tacit") + std::to_string(tacitno) + ".out"; + // create if non-existent, truncate if exists + int tacitlogfd = open(tacitlogname.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (tacitlogfd == -1) { + fprintf(stderr, "Failed to open TACIT%d log file: %s\n", tacitno, tacitlogname.c_str()); + return nullptr; + } + return std::make_unique(tacitno, tacitlogfd); +} + +tacit_t::tacit_t(simif_t &simif, + StreamEngine &stream, + int tacitno, + const std::vector &args, + int stream_idx, + int stream_depth) + : streaming_bridge_driver_t(simif, stream, &KIND), + handler(create_handler(args, tacitno)), + stream_idx(stream_idx), + stream_depth(stream_depth) {} + +tacit_t::~tacit_t() = default; + +void tacit_t::tick() { + drain_stream(STREAM_WIDTH_BYTES); +} + +void tacit_t::finish() { + pull_flush(stream_idx); + drain_stream(0); + handler->flush_buffer(); +} + +void tacit_t::drain_stream(size_t minimum_batch_bytes) { + const size_t max_batch_bytes = + static_cast(stream_depth) * STREAM_WIDTH_BYTES; + if (!handler || stream_depth == 0 || max_batch_bytes == 0) { + return; + } + + page_aligned_sized_array(outbuf, STREAM_WIDTH_BYTES * stream_depth); + + size_t min_bytes = minimum_batch_bytes; + while (true) { + const size_t bytes_received = + pull(stream_idx, outbuf, max_batch_bytes, min_bytes); + if (bytes_received == 0) { + break; + } + + auto *byte_buf = reinterpret_cast(outbuf); + for (size_t i = 0; i < bytes_received; ++i) { + handler->put(byte_buf[i]); + } + + if (bytes_received < max_batch_bytes && min_bytes == 0) { + break; + } + + min_bytes = 0; + } +} diff --git a/generators/firechip/bridgestubs/src/main/cc/bridges/tacit.h b/generators/firechip/bridgestubs/src/main/cc/bridges/tacit.h new file mode 100644 index 0000000000..8e83f78f21 --- /dev/null +++ b/generators/firechip/bridgestubs/src/main/cc/bridges/tacit.h @@ -0,0 +1,60 @@ +// See LICENSE for license details + +#ifndef __TACITBRIDGE_H +#define __TACITBRIDGE_H + +#include "core/bridge_driver.h" + +#include +#include +#include +#include +#include +#include + +class StreamEngine; + +/** + * Structure carrying the addresses of all fixed MMIO ports. + * + * This structure is instantiated when all bridges are populated based on + * the target configuration. + */ +struct TACITBRIDGEMODULE_struct { +}; + +class tacit_handler { +public: + virtual ~tacit_handler() = default; + virtual void put(uint8_t data) = 0; + virtual void flush_buffer() = 0; +}; + +class tacit_t final : public streaming_bridge_driver_t { +public: + /// The identifier for the bridge type used for casts. + static char KIND; + + /// Creates a bridge which interacts with standard streams or PTY. + tacit_t(simif_t &simif, + StreamEngine &stream, + int tacitno, + const std::vector &args, + int stream_idx, + int stream_depth); + + ~tacit_t() override; + + void tick() override; + void finish() override; + +private: + std::unique_ptr handler; + + const int stream_idx; + const int stream_depth; + + void drain_stream(size_t minimum_batch_bytes); +}; + +#endif // __TACITBRIDGE_H diff --git a/generators/firechip/bridgestubs/src/main/scala/tacit/TacitBridge.scala b/generators/firechip/bridgestubs/src/main/scala/tacit/TacitBridge.scala new file mode 100644 index 0000000000..e6ccb7ca7c --- /dev/null +++ b/generators/firechip/bridgestubs/src/main/scala/tacit/TacitBridge.scala @@ -0,0 +1,36 @@ +// see LICENSE for license details + +package firechip.bridgestubs + +import chisel3._ +import chisel3.util._ + +import org.chipsalliance.cde.config.Parameters + +import firesim.lib.bridgeutils._ + +import firechip.bridgeinterfaces._ + +class TacitBridge() extends BlackBox + with Bridge[HostPortIO[TraceRawByteBridgeTargetIO]] { + + + val moduleName = "firechip.goldengateimplementations.TacitBridgeModule" + + val io = IO(new TraceRawByteBridgeTargetIO) + val bridgeIO = HostPort(io) + + val constructorArg = Some(TraceRawByteKey()) + + generateAnnotations() +} + +object TacitBridge { + def apply(clock: Clock, byte: tacit.TraceSinkRawByteBundle, reset: Bool): TacitBridge = { + val ep = Module(new TacitBridge) + ep.io.byte.out <> byte.out + ep.io.reset := reset + ep.io.clock := clock + ep + } +} \ No newline at end of file diff --git a/generators/firechip/bridgestubs/src/main/scala/tacit/TacitModule.scala b/generators/firechip/bridgestubs/src/main/scala/tacit/TacitModule.scala new file mode 100644 index 0000000000..311d193040 --- /dev/null +++ b/generators/firechip/bridgestubs/src/main/scala/tacit/TacitModule.scala @@ -0,0 +1,16 @@ +// See LICENSE for license details. + +package firechip.bridgestubs + +import chisel3._ + +import org.chipsalliance.cde.config.Parameters + +class TacitDUT(implicit val p: Parameters) extends Module { + val ep = Module(new TacitBridge) + ep.io.byte.out := ep.io.byte.out + ep.io.reset := reset + ep.io.clock := clock +} + +class TacitModule(implicit p: Parameters) extends firesim.lib.testutils.PeekPokeHarness(() => new TacitDUT) diff --git a/generators/firechip/chip/src/main/scala/BridgeBinders.scala b/generators/firechip/chip/src/main/scala/BridgeBinders.scala index 5a05550fc2..dbdc63c236 100644 --- a/generators/firechip/chip/src/main/scala/BridgeBinders.scala +++ b/generators/firechip/chip/src/main/scala/BridgeBinders.scala @@ -141,6 +141,12 @@ class WithSuccessBridge extends HarnessBinder({ } }) +class WithTacitBridge extends HarnessBinder({ + case (th: FireSim, port: TraceSinkRawBytePort, chipId: Int) => { + TacitBridge(th.harnessBinderClock, port.io, th.harnessBinderReset.asBool) + } +}) + // Shorthand to register all of the provided bridges above class WithDefaultFireSimBridges extends Config( new WithTSIBridgeAndHarnessRAMOverSerialTL ++ diff --git a/generators/firechip/chip/src/main/scala/TargetConfigs.scala b/generators/firechip/chip/src/main/scala/TargetConfigs.scala index 879ac198b6..34de3a5985 100644 --- a/generators/firechip/chip/src/main/scala/TargetConfigs.scala +++ b/generators/firechip/chip/src/main/scala/TargetConfigs.scala @@ -352,3 +352,31 @@ class FireSimLargeBoomSV39CospikeConfig extends Config( new WithFireSimConfigTweaks++ new freechips.rocketchip.rocket.WithSV39 ++ new chipyard.LargeBoomV3Config) + +//********************************************************************************** +// Tacit Configurations +//*********************************************************************************/ +class FireSimRocketTacitConfig extends Config( + new WithTacitBridge ++ + new WithDefaultFireSimBridges ++ + new WithFireSimConfigTweaks++ + new chipyard.TacitRocketRawByteConfig) + +class FireSimDualRocketTacitConfig extends Config( + new WithTacitBridge ++ + new WithDefaultFireSimBridges ++ + new WithFireSimConfigTweaks++ + new chipyard.TacitDualRocketRawByteConfig) + +class FireSimRocketTacitNICConfig extends Config( + new WithNIC ++ + new WithTacitBridge ++ + new WithDefaultFireSimBridges ++ + new WithFireSimConfigTweaks++ + new chipyard.TacitRocketRawByteConfig) + +class FireSimRocketTacitPrefetchConfig extends Config( + new WithTacitBridge ++ + new WithDefaultFireSimBridges ++ + new WithFireSimConfigTweaks++ + new chipyard.TacitRocketRawBytePrefetchConfig) \ No newline at end of file diff --git a/generators/firechip/goldengateimplementations/src/main/scala/TacitBridge.scala b/generators/firechip/goldengateimplementations/src/main/scala/TacitBridge.scala new file mode 100644 index 0000000000..1100352c2a --- /dev/null +++ b/generators/firechip/goldengateimplementations/src/main/scala/TacitBridge.scala @@ -0,0 +1,85 @@ +// See LICENSE for license details + +package firechip.goldengateimplementations + +import chisel3._ +import chisel3.util._ + +import org.chipsalliance.cde.config.Parameters + +import midas.widgets._ +import firesim.lib.bridgeutils._ + +import firechip.bridgeinterfaces._ + +// copied from testchipip.serdes.SerialWidthAggregator +class SerialWidthAggregator(narrowW: Int, wideW: Int) extends Module { + require(wideW > narrowW) + require(wideW % narrowW == 0) + val io = IO(new Bundle { + val narrow = Flipped(Decoupled(UInt(narrowW.W))) + val wide = Decoupled(UInt(wideW.W)) + }) + + val beats = wideW / narrowW + + val narrow_beats = RegInit(0.U(log2Ceil(beats).W)) + val narrow_last_beat = narrow_beats === (beats-1).U + val narrow_data = Reg(Vec(beats-1, UInt(narrowW.W))) + + io.narrow.ready := Mux(narrow_last_beat, io.wide.ready, true.B) + when (io.narrow.fire) { + narrow_beats := Mux(narrow_last_beat, 0.U, narrow_beats + 1.U) + when (!narrow_last_beat) { narrow_data(narrow_beats) := io.narrow.bits } + } + io.wide.valid := narrow_last_beat && io.narrow.valid + io.wide.bits := Cat(io.narrow.bits, narrow_data.asUInt) +} + +class TacitBridgeModule(key: TraceRawByteKey)(implicit p: Parameters) + extends BridgeModule[HostPortIO[TraceRawByteBridgeTargetIO]]()(p) + with StreamToHostCPU { + + val toHostCPUQueueDepth = 6144 + lazy val module = new BridgeModuleImp(this) { + val io = IO(new WidgetIO()) + + val hPort = IO(HostPort(new TraceRawByteBridgeTargetIO)) + + val aggregator = Module(new SerialWidthAggregator(8, BridgeStreamConstants.streamWidthBits)) + val txfifo = Module(new Queue(UInt(BridgeStreamConstants.streamWidthBits.W), 3072)) + + val target = hPort.hBits.byte + + val fire = hPort.toHost.hValid && + hPort.fromHost.hReady && + txfifo.io.enq.ready + + val targetReset = fire & hPort.hBits.reset + txfifo.reset := reset.asBool || targetReset + + hPort.toHost.hReady := fire + hPort.fromHost.hValid := fire + + aggregator.io.narrow.bits := target.out.bits + aggregator.io.narrow.valid := target.out.valid && fire + target.out.ready := aggregator.io.narrow.ready && fire + + txfifo.io.enq <> aggregator.io.wide + streamEnq <> txfifo.io.deq + + genCRFile() + + override def genHeader(base: BigInt, memoryRegions: Map[String, BigInt], sb: StringBuilder): Unit = { + genConstructor( + base, + sb, + "tacit_t", + "tacit", Seq( + UInt32(toHostStreamIdx), + UInt32(toHostCPUQueueDepth), + ), + hasStreams = true) + } + } +} \ No newline at end of file diff --git a/generators/rocket-chip b/generators/rocket-chip index 8f1e33b253..f82a9d4747 160000 --- a/generators/rocket-chip +++ b/generators/rocket-chip @@ -1 +1 @@ -Subproject commit 8f1e33b253e3bce741861c0a2e3ba8b7ff85b292 +Subproject commit f82a9d4747c66a871a697c261ccd5cb503c2f3df diff --git a/generators/shuttle b/generators/shuttle index cb9313d036..51f59f6387 160000 --- a/generators/shuttle +++ b/generators/shuttle @@ -1 +1 @@ -Subproject commit cb9313d03637ca52d0ccf27ac8e986a0d454befb +Subproject commit 51f59f63879d3317c8e1f05af0e3a96cafb5b27d diff --git a/generators/tacit b/generators/tacit index fe61365292..1ce2313236 160000 --- a/generators/tacit +++ b/generators/tacit @@ -1 +1 @@ -Subproject commit fe61365292ef1fa60410a2a91c48a3e3d22b1a75 +Subproject commit 1ce2313236c3a3878787dc7c195a2437352e0c99 diff --git a/software/baremetal-ide b/software/baremetal-ide index 6e01715bea..601b2f0d3c 160000 --- a/software/baremetal-ide +++ b/software/baremetal-ide @@ -1 +1 @@ -Subproject commit 6e01715bea3e4a4015138e9583e40caa08205408 +Subproject commit 601b2f0d3cc834ac04720c8fc35c56bdb8124003 diff --git a/software/embench/.gitignore b/software/embench/.gitignore index 378eac25d3..4265d2f494 100644 --- a/software/embench/.gitignore +++ b/software/embench/.gitignore @@ -1 +1,218 @@ build + +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[codz] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py.cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +# Pipfile.lock + +# UV +# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# uv.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +# poetry.lock +# poetry.toml + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +# pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python. +# https://pdm-project.org/en/latest/usage/project/#working-with-version-control +# pdm.lock +# pdm.toml +.pdm-python +.pdm-build/ + +# pixi +# Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control. +# pixi.lock +# Pixi creates a virtual environment in the .pixi directory, just like venv module creates one +# in the .venv directory. It is recommended not to include this directory in version control. +.pixi + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# Redis +*.rdb +*.aof +*.pid + +# RabbitMQ +mnesia/ +rabbitmq/ +rabbitmq-data/ + +# ActiveMQ +activemq-data/ + +# SageMath parsed files +*.sage.py + +# Environments +.env +.envrc +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +# .idea/ + +# Abstra +# Abstra is an AI-powered process automation framework. +# Ignore directories containing user credentials, local state, and settings. +# Learn more at https://abstra.io/docs +.abstra/ + +# Visual Studio Code +# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore +# that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore +# and can be added to the global gitignore or merged into this file. However, if you prefer, +# you could uncomment the following to ignore the entire vscode folder +# .vscode/ + +# Ruff stuff: +.ruff_cache/ + +# PyPI configuration file +.pypirc + +# Marimo +marimo/_static/ +marimo/_lsp/ +__marimo__/ + +# Streamlit +.streamlit/secrets.toml \ No newline at end of file diff --git a/software/embench/run_all_spike.sh b/software/embench/run_all_spike.sh new file mode 100755 index 0000000000..4265e94a5f --- /dev/null +++ b/software/embench/run_all_spike.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash +set -e + +OUTPUT_DIR=$(pwd)/logs +RESULTS_DIR=$(pwd)/results +SCRIPTS_DIR=$(pwd)/scripts + +mkdir -p $OUTPUT_DIR +mkdir -p $RESULTS_DIR + +bmarks=("aha-mont64" "crc32" "cubic" "edn" "huffbench" + "matmult-int" "minver" "nbody" "nettle-aes" + "nettle-sha256" "nsichneu" "picojpeg" + "qrduino" "sglib-combined" "slre" "st" + "statemate" "ud" "wikisort") +for bmark in "${bmarks[@]}" +do + spike -l build/$bmark 2>$OUTPUT_DIR/$bmark.log + python3 $SCRIPTS_DIR/parse_log.py $OUTPUT_DIR/$bmark.log > $RESULTS_DIR/$bmark.txt +done \ No newline at end of file diff --git a/software/embench/scripts/draw_bar.py b/software/embench/scripts/draw_bar.py new file mode 100644 index 0000000000..d8e52a4703 --- /dev/null +++ b/software/embench/scripts/draw_bar.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python3 +""" +Generate a stacked bar chart summarising control-flow instruction counts per benchmark. +""" + +import re +from pathlib import Path + +import matplotlib.pyplot as plt + + +LINE_RE = re.compile(r"^(.*?):\s+(\d+)\s*$") + + +def parse_counts(path: Path) -> dict[str, int]: + data: dict[str, int] = {} + for raw_line in path.read_text().splitlines(): + match = LINE_RE.match(raw_line) + if not match: + continue + key = match.group(1).strip().lower() + value = int(match.group(2)) + data[key] = value + required_keys = {"total control flow change counts", "branch counts", "ij counts", "uj counts"} + missing = required_keys - data.keys() + if missing: + raise ValueError(f"{path.name} is missing keys: {', '.join(sorted(missing))}") + return data + + +def main() -> None: + script_dir = Path(__file__).resolve().parent + results_dir = script_dir.parent / "results" + result_files = sorted(results_dir.glob("*.txt")) + if not result_files: + raise SystemExit(f"No .txt result files found in {results_dir}") + + benchmarks: list[str] = [] + branch_pct: list[float] = [] + ij_pct: list[float] = [] + uj_pct: list[float] = [] + + for result_file in result_files: + counts = parse_counts(result_file) + branch = counts["branch counts"] + ij = counts["ij counts"] + uj = counts["uj counts"] + total = branch + ij + uj + if total == 0: + raise ValueError(f"{result_file.name} reports zero aggregated control-flow counts") + benchmarks.append(result_file.stem) + branch_pct.append((branch / total) * 100.0) + ij_pct.append((ij / total) * 100.0) + uj_pct.append((uj / total) * 100.0) + + indices = range(len(benchmarks)) + branch_array = branch_pct + ij_array = ij_pct + uj_array = uj_pct + + plt.rc('font', size = 14) + fig, ax = plt.subplots(figsize=(max(6, len(benchmarks) * 0.5), 6)) + + ax.bar(indices, branch_array, label="Branch") + ax.bar(indices, ij_array, bottom=branch_array, label="Inferable Jumps") + cumulative = [b + i for b, i in zip(branch_array, ij_array)] + ax.bar(indices, uj_array, bottom=cumulative, label="Uninferable Jumps") + + ax.set_xticks(list(indices)) + ax.set_xticklabels(benchmarks, rotation=45, ha="right") + ax.set_ylabel("Percentage of control-flow instructions") + ax.set_title("Control-flow instruction breakdown per benchmark") + ax.set_ylim(0, 100) + ax.legend() + ax.margins(x=0.01) + fig.tight_layout() + + output_path = results_dir / "control_flow_counts.png" + fig.savefig(output_path, dpi=300) + plt.close(fig) + print(f"Saved stacked bar chart to {output_path}") + + +if __name__ == "__main__": + main() diff --git a/software/embench/scripts/parse_log.py b/software/embench/scripts/parse_log.py new file mode 100644 index 0000000000..650b60be9a --- /dev/null +++ b/software/embench/scripts/parse_log.py @@ -0,0 +1,45 @@ +# first arg is the log file +import re +import sys + +BRANCH_OPCODES = ["beq", "bge", "bgeu", "blt", "bltu", "bne", "beqz", "bnez", + "bgez", "blez", "bltz", "bgtz", "bgt", "ble", "bgtu", "bleu", + "c.beqz", "c.bnez", "c.bltz", "c.bgez"] +IJ_OPCODES = ["jal", "j", "call", "tail", "c.j", "c.jal"] +UJ_OPCODES = ["jalr", "jr", "c.jr", "c.jalr", "ret"] + +# example line: +# core 0: 0x0000000080000000 (0x00004081) c.li ra, 0 +# extract PC and opcode +pattern = r'core\s+0:\s+0x([0-9a-fA-F]+)\s+\((0x[0-9a-fA-F]+)\)\s+([a-zA-Z0-9_.]+)\s*(.*)' + + +log_file = sys.argv[1] + +with open(log_file, 'r') as f: + lines = f.readlines() + + +total_control_flow_change_counts = 0 +branch_counts = 0 +ij_counts = 0 +uj_counts = 0 + +for line in lines: + match = re.match(pattern, line) + if match: + pc = match.group(1) + opcode = match.group(3) + # print(f"PC: {pc}, Opcode: {opcode}") + if opcode in BRANCH_OPCODES: + total_control_flow_change_counts += 1 + branch_counts += 1 + elif opcode in IJ_OPCODES: + ij_counts += 1 + elif opcode in UJ_OPCODES: + uj_counts += 1 + +print(f"Total control flow change counts: {total_control_flow_change_counts}") +print(f"Branch counts: {branch_counts}") +print(f"IJ counts: {ij_counts}") +print(f"UJ counts: {uj_counts}") \ No newline at end of file diff --git a/software/firemarshal b/software/firemarshal index 21119e5ce9..2fdfae665d 160000 --- a/software/firemarshal +++ b/software/firemarshal @@ -1 +1 @@ -Subproject commit 21119e5ce922ff9302f0bc9d2d7349c77f7ac064 +Subproject commit 2fdfae665d2d97b170e1aee5866084941aa14257 diff --git a/software/spec2017 b/software/spec2017 index 83e3311047..2e99bf7cf2 160000 --- a/software/spec2017 +++ b/software/spec2017 @@ -1 +1 @@ -Subproject commit 83e33110472c47aaa762257ed7c053ff1278834c +Subproject commit 2e99bf7cf27905e2bdaa8931d31e1eedbd608f1a diff --git a/software/tacit_decoder b/software/tacit_decoder index acbbd2e2e5..0a3222b21e 160000 --- a/software/tacit_decoder +++ b/software/tacit_decoder @@ -1 +1 @@ -Subproject commit acbbd2e2e5344548a464460bff9ee9b9ff437209 +Subproject commit 0a3222b21e3228700450ec2146e8daa21034c9e9