Skip to content
Draft
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
2 changes: 1 addition & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -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)))
Expand Down
1 change: 1 addition & 0 deletions generators/chipyard/src/main/scala/DigitalTop.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -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 ++

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)))
}
})
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
13 changes: 13 additions & 0 deletions generators/chipyard/src/main/scala/iobinders/IOBinders.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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}

Expand Down Expand Up @@ -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 =>
Expand Down
4 changes: 4 additions & 0 deletions generators/chipyard/src/main/scala/iobinders/Ports.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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]

Original file line number Diff line number Diff line change
@@ -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
152 changes: 152 additions & 0 deletions generators/firechip/bridgestubs/src/main/cc/bridges/tacit.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
// See LICENSE for license details

#include "tacit.h"
#include "core/simif.h"

#include <fcntl.h>
#include <sys/stat.h>

#include <stdio.h>
#include <stdlib.h>
#include <array>
#include <errno.h>
#include <string.h>
#include <unistd.h>

// #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<uint8_t, BUFFER_SIZE> 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<size_t>(bytes_written);
continue;
}
if (bytes_written == -1 && errno == EINTR) {
continue;
}
fatal_io_error(tacitlogfd, "write");
}
buffered_bytes = 0;
}

static std::unique_ptr<tacit_handler>
create_handler(const std::vector<std::string> &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<tacit_handler_impl>(tacitno, tacitlogfd);
}

tacit_t::tacit_t(simif_t &simif,
StreamEngine &stream,
int tacitno,
const std::vector<std::string> &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<size_t>(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<uint8_t *>(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;
}
}
60 changes: 60 additions & 0 deletions generators/firechip/bridgestubs/src/main/cc/bridges/tacit.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// See LICENSE for license details

#ifndef __TACITBRIDGE_H
#define __TACITBRIDGE_H

#include "core/bridge_driver.h"

#include <cstdint>
#include <memory>
#include <optional>
#include <signal.h>
#include <string>
#include <vector>

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<std::string> &args,
int stream_idx,
int stream_depth);

~tacit_t() override;

void tick() override;
void finish() override;

private:
std::unique_ptr<tacit_handler> handler;

const int stream_idx;
const int stream_depth;

void drain_stream(size_t minimum_batch_bytes);
};

#endif // __TACITBRIDGE_H
Original file line number Diff line number Diff line change
@@ -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
}
}
Original file line number Diff line number Diff line change
@@ -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)
Loading
Loading