Merge pull request #1420 from ucb-bar/fixes
Various improvements and fixes
This commit is contained in:
2
.github/scripts/check-commit.sh
vendored
2
.github/scripts/check-commit.sh
vendored
@@ -45,7 +45,7 @@ search () {
|
||||
done
|
||||
}
|
||||
|
||||
submodules=("cva6" "boom" "ibex" "hwacha" "icenet" "nvdla" "rocket-chip" "sha3" "sifive-blocks" "sifive-cache" "testchipip" "riscv-sodor" "mempress")
|
||||
submodules=("cva6" "boom" "ibex" "gemmini" "hwacha" "icenet" "nvdla" "rocket-chip" "sha3" "sifive-blocks" "sifive-cache" "testchipip" "riscv-sodor" "mempress")
|
||||
dir="generators"
|
||||
branches=("master" "main" "dev")
|
||||
search
|
||||
|
||||
29
.github/workflows/chipyard-run-tests.yml
vendored
29
.github/workflows/chipyard-run-tests.yml
vendored
@@ -390,6 +390,35 @@ jobs:
|
||||
|
||||
##########################################################################
|
||||
|
||||
chipyard-spike-gemmini-run-tests:
|
||||
name: chipyard-spike-gemmini-run-tests
|
||||
needs: prepare-chipyard-accels # technically doesn't depend on RTL but should be after the build.sh for Gemmini
|
||||
runs-on: ferry
|
||||
steps:
|
||||
- name: Delete old checkout
|
||||
run: |
|
||||
ls -alh .
|
||||
rm -rf ${{ github.workspace }}/* || true
|
||||
rm -rf ${{ github.workspace }}/.* || true
|
||||
ls -alh .
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: Git workaround
|
||||
uses: ./.github/actions/git-workaround
|
||||
- name: Create conda env
|
||||
uses: ./.github/actions/create-conda-env
|
||||
- name: Build Gemmini FireMarshal
|
||||
run: |
|
||||
conda activate ${{ env.conda-env-name-no-time }}-$(date --date "${{ env.workflow-timestamp }}" +%Y%m%d)-riscv-tools
|
||||
cd ${{ github.workspace }} && ./scripts/init-submodules-no-riscv-tools.sh --force
|
||||
cd ${{ github.workspace }} && source ./scripts/fix-open-files.sh
|
||||
git submodule update --init software/firemarshal && cd software/firemarshal && ./init-submodules.sh
|
||||
cd ${{ github.workspace }}/generators/gemmini/software && ${{ github.workspace }}/software/firemarshal/marshal -v -d build gemmini-smoke.json
|
||||
- name: Running Gemmini FireMarshal smoke test
|
||||
run: |
|
||||
conda activate ${{ env.conda-env-name-no-time }}-$(date --date "${{ env.workflow-timestamp }}" +%Y%m%d)-riscv-tools
|
||||
cd ${{ github.workspace }}/generators/gemmini/software && ${{ github.workspace }}/software/firemarshal/marshal -v -d launch -s gemmini-smoke.json
|
||||
|
||||
chipyard-rocket-run-tests:
|
||||
name: chipyard-rocket-run-tests
|
||||
needs: prepare-chipyard-cores
|
||||
|
||||
@@ -32,4 +32,21 @@ In this configuration, Spike is cache-coherent, and communicates with the uncore
|
||||
|
||||
make CONFIG=SpikeConfig run-binary BINARY=hello.riscv
|
||||
|
||||
Spike-as-a-Tile also supports Tightly-Coupled-Memory (TCM) for the SpikeTile, in which the main system memory is entirely modeled
|
||||
within the Spike tile, allowing for very fast simulatoin performance.
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
make CONFIG=SpikeUltraFastConfig run-binary BINARY=hello.riscv
|
||||
|
||||
Spike-as-a-Tile can be configured with custom IPC, commit logging, and other behaviors. Spike-specific flags can be added as plusargs to ``EXTRA_SIM_FLAGS``
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
make CONFIG=SpikeUltraFastConfig run-binary-hex BINARY=hello.riscv EXTRA_SPIKE_FLAGS="+spike-ipc=10000 +spike-fast-clint +spike-debug"
|
||||
|
||||
|
||||
* ``+spike-ipc=``: Sets the maximum number of instructions Spike can retire in a single "tick", or cycle of the uncore simulation.
|
||||
* ``+spike-fast-clint``: Enables fast-forwarding through WFI stalls by generating fake timer interrupts
|
||||
* ``+spike-debug``: Enables debug Spike logging
|
||||
* ``+spike-verbose``: Enables Spike commit-log generation
|
||||
|
||||
Submodule generators/boom updated: deae9f7046...051dbadb6d
@@ -6,6 +6,9 @@
|
||||
#include <sstream>
|
||||
#include <vpi_user.h>
|
||||
#include <svdpi.h>
|
||||
#include "testchip_tsi.h"
|
||||
|
||||
extern testchip_tsi_t* tsi;
|
||||
|
||||
enum transfer_t {
|
||||
NToB,
|
||||
@@ -73,9 +76,18 @@ public:
|
||||
void dcache_b(uint64_t address, uint64_t source, int param);
|
||||
bool dcache_c(uint64_t *address, uint64_t* source, int* param, unsigned char* voluntary, unsigned char* has_data, uint64_t* data[8]);
|
||||
void dcache_d(uint64_t sourceid, uint64_t data[8], unsigned char has_data, unsigned char grantack);
|
||||
|
||||
void tcm_a(uint64_t address, uint64_t data, uint32_t mask, uint32_t opcode, uint32_t size);
|
||||
bool tcm_d(uint64_t *data);
|
||||
|
||||
void loadmem(const char* fname);
|
||||
|
||||
void drain_stq();
|
||||
bool stq_empty() { return st_q.size() == 0; };
|
||||
|
||||
const cfg_t &get_cfg() const { return cfg; }
|
||||
const std::map<size_t, processor_t*>& get_harts() const { return harts; }
|
||||
|
||||
~chipyard_simif_t() { };
|
||||
chipyard_simif_t(size_t icache_ways,
|
||||
size_t icache_sets,
|
||||
@@ -86,9 +98,17 @@ public:
|
||||
char* readonly_uncacheable,
|
||||
char* executable,
|
||||
size_t icache_sourceids,
|
||||
size_t dcache_sourceids);
|
||||
size_t dcache_sourceids,
|
||||
size_t tcm_base,
|
||||
size_t tcm_size,
|
||||
const char* isastr,
|
||||
size_t pmpregions);
|
||||
uint64_t cycle;
|
||||
bool use_stq;
|
||||
htif_t *htif;
|
||||
bool fast_clint;
|
||||
cfg_t cfg;
|
||||
std::map<size_t, processor_t*> harts;
|
||||
private:
|
||||
bool handle_cache_access(reg_t addr, size_t len,
|
||||
uint8_t* load_bytes,
|
||||
@@ -133,6 +153,11 @@ private:
|
||||
uint64_t mmio_stdata;
|
||||
size_t mmio_len;
|
||||
uint64_t mmio_lddata;
|
||||
|
||||
uint64_t tcm_base;
|
||||
uint64_t tcm_size;
|
||||
uint8_t* tcm;
|
||||
std::vector<uint64_t> tcm_q;
|
||||
};
|
||||
|
||||
class tile_t {
|
||||
@@ -163,6 +188,7 @@ extern "C" void spike_tile(int hartid, char* isa,
|
||||
int dcache_sets, int dcache_ways,
|
||||
char* cacheable, char* uncacheable, char* readonly_uncacheable, char* executable,
|
||||
int icache_sourceids, int dcache_sourceids,
|
||||
long long int tcm_base, long long int tcm_size,
|
||||
long long int reset_vector,
|
||||
long long int ipc,
|
||||
long long int cycle,
|
||||
@@ -237,7 +263,18 @@ extern "C" void spike_tile(int hartid, char* isa,
|
||||
int* mmio_a_size,
|
||||
|
||||
unsigned char mmio_d_valid,
|
||||
long long int mmio_d_data
|
||||
long long int mmio_d_data,
|
||||
|
||||
unsigned char tcm_a_valid,
|
||||
long long int tcm_a_address,
|
||||
long long int tcm_a_data,
|
||||
int tcm_a_mask,
|
||||
int tcm_a_opcode,
|
||||
int tcm_a_size,
|
||||
|
||||
unsigned char* tcm_d_valid,
|
||||
unsigned char tcm_d_ready,
|
||||
long long int* tcm_d_data
|
||||
)
|
||||
{
|
||||
if (!host) {
|
||||
@@ -248,36 +285,26 @@ extern "C" void spike_tile(int hartid, char* isa,
|
||||
if (tiles.find(hartid) == tiles.end()) {
|
||||
printf("Constructing spike processor_t\n");
|
||||
isa_parser_t *isa_parser = new isa_parser_t(isa, "MSU");
|
||||
std::string* isastr = new std::string(isa);
|
||||
chipyard_simif_t* simif = new chipyard_simif_t(icache_ways, icache_sets,
|
||||
dcache_ways, dcache_sets,
|
||||
cacheable, uncacheable, readonly_uncacheable, executable,
|
||||
icache_sourceids, dcache_sourceids);
|
||||
std::string* isastr = new std::string(isa);
|
||||
cfg_t* cfg = new cfg_t(std::make_pair(0, 0),
|
||||
nullptr,
|
||||
isastr->c_str(),
|
||||
"MSU",
|
||||
"vlen:128,elen:64",
|
||||
false,
|
||||
endianness_little,
|
||||
pmpregions,
|
||||
std::vector<mem_cfg_t>(),
|
||||
std::vector<size_t>(),
|
||||
false,
|
||||
0);
|
||||
icache_sourceids, dcache_sourceids,
|
||||
tcm_base, tcm_size,
|
||||
isastr->c_str(), pmpregions);
|
||||
processor_t* p = new processor_t(isa_parser,
|
||||
cfg,
|
||||
&simif->get_cfg(),
|
||||
simif,
|
||||
hartid,
|
||||
false,
|
||||
log_file->get(),
|
||||
sout);
|
||||
|
||||
p->enable_log_commits();
|
||||
simif->harts[hartid] = p;
|
||||
|
||||
s_vpi_vlog_info vinfo;
|
||||
if (!vpi_get_vlog_info(&vinfo))
|
||||
abort();
|
||||
std::string loadmem_file = "";
|
||||
for (int i = 1; i < vinfo.argc; i++) {
|
||||
std::string arg(vinfo.argv[i]);
|
||||
if (arg == "+spike-debug") {
|
||||
@@ -286,7 +313,18 @@ extern "C" void spike_tile(int hartid, char* isa,
|
||||
if (arg == "+spike-stq") {
|
||||
simif->use_stq = true;
|
||||
}
|
||||
if (arg.find("+loadmem=") == 0) {
|
||||
loadmem_file = arg.substr(strlen("+loadmem="));
|
||||
}
|
||||
if (arg == "+spike-fast-clint") {
|
||||
simif->fast_clint = true;
|
||||
}
|
||||
if (arg == "+spike-verbose") {
|
||||
p->enable_log_commits();
|
||||
}
|
||||
}
|
||||
if (loadmem_file != "" && tcm_size > 0)
|
||||
simif->loadmem(loadmem_file.c_str());
|
||||
|
||||
p->reset();
|
||||
p->get_state()->pc = reset_vector;
|
||||
@@ -296,6 +334,9 @@ extern "C" void spike_tile(int hartid, char* isa,
|
||||
tile_t* tile = tiles[hartid];
|
||||
chipyard_simif_t* simif = tile->simif;
|
||||
processor_t* proc = tile->proc;
|
||||
if (!simif->htif && tsi) {
|
||||
simif->htif = (htif_t*) tsi;
|
||||
}
|
||||
|
||||
simif->cycle = cycle;
|
||||
if (debug) {
|
||||
@@ -357,6 +398,13 @@ extern "C" void spike_tile(int hartid, char* isa,
|
||||
if (mmio_d_valid) {
|
||||
simif->mmio_d(mmio_d_data);
|
||||
}
|
||||
|
||||
if (tcm_a_valid) {
|
||||
simif->tcm_a(tcm_a_address, tcm_a_data, tcm_a_mask, tcm_a_opcode, tcm_a_size);
|
||||
}
|
||||
if (tcm_d_ready) {
|
||||
*tcm_d_valid = simif->tcm_d((uint64_t*)tcm_d_data);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -369,14 +417,34 @@ chipyard_simif_t::chipyard_simif_t(size_t icache_ways,
|
||||
char* readonly_uncacheable,
|
||||
char* executable,
|
||||
size_t ic_sourceids,
|
||||
size_t dc_sourceids
|
||||
size_t dc_sourceids,
|
||||
size_t tcm_base,
|
||||
size_t tcm_size,
|
||||
const char* isastr,
|
||||
size_t pmpregions
|
||||
) :
|
||||
cycle(0),
|
||||
use_stq(false),
|
||||
htif(nullptr),
|
||||
fast_clint(false),
|
||||
cfg(std::make_pair(0, 0),
|
||||
nullptr,
|
||||
isastr,
|
||||
"MSU",
|
||||
"vlen:128,elen:64",
|
||||
false,
|
||||
endianness_little,
|
||||
pmpregions,
|
||||
std::vector<mem_cfg_t>(),
|
||||
std::vector<size_t>(),
|
||||
false,
|
||||
0),
|
||||
icache_ways(icache_ways),
|
||||
icache_sets(icache_sets),
|
||||
dcache_ways(dcache_ways),
|
||||
dcache_sets(dcache_sets),
|
||||
tcm_base(tcm_base),
|
||||
tcm_size(tcm_size),
|
||||
mmio_valid(false),
|
||||
mmio_inflight(false)
|
||||
{
|
||||
@@ -432,6 +500,8 @@ chipyard_simif_t::chipyard_simif_t(size_t icache_ways,
|
||||
uint64_t size_int = std::stoul(size);
|
||||
executables.push_back(mem_region_t { base_int, size_int });
|
||||
}
|
||||
|
||||
tcm = (uint8_t*)malloc(tcm_size);
|
||||
}
|
||||
|
||||
bool chipyard_simif_t::reservable(reg_t addr) {
|
||||
@@ -440,12 +510,20 @@ bool chipyard_simif_t::reservable(reg_t addr) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (addr >= tcm_base && addr < tcm_base + tcm_size) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool chipyard_simif_t::mmio_fetch(reg_t addr, size_t len, uint8_t* bytes) {
|
||||
bool executable = false;
|
||||
|
||||
if (addr >= tcm_base && addr < tcm_base + tcm_size) {
|
||||
memcpy(bytes, tcm + addr - tcm_base, len);
|
||||
return true;
|
||||
}
|
||||
|
||||
for (auto& r: executables) {
|
||||
if (addr >= r.base && addr + len <= r.base + r.size) {
|
||||
executable = true;
|
||||
@@ -466,6 +544,10 @@ bool chipyard_simif_t::mmio_load(reg_t addr, size_t len, uint8_t* bytes) {
|
||||
bool found = false;
|
||||
bool cacheable = false;
|
||||
bool readonly = false;
|
||||
if (addr >= tcm_base && addr < tcm_base + tcm_size) {
|
||||
memcpy(bytes, tcm + addr - tcm_base, len);
|
||||
return true;
|
||||
}
|
||||
for (auto& r: cacheables) {
|
||||
if (addr >= r.base && addr + len <= r.base + r.size) {
|
||||
cacheable = true;
|
||||
@@ -829,9 +911,14 @@ bool chipyard_simif_t::dcache_c(uint64_t* address, uint64_t* source, int* param,
|
||||
}
|
||||
|
||||
bool chipyard_simif_t::mmio_store(reg_t addr, size_t len, const uint8_t* bytes) {
|
||||
if (addr >= tcm_base && addr < tcm_base + tcm_size) {
|
||||
memcpy(tcm + addr - tcm_base, bytes, len);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool found = false;
|
||||
bool cacheable = false;
|
||||
for (auto& r: cacheables) {
|
||||
for (auto& r: cacheables) {
|
||||
if (addr >= r.base && addr + len <= r.base + r.size) {
|
||||
cacheable = true;
|
||||
found = true;
|
||||
@@ -899,27 +986,108 @@ void chipyard_simif_t::dcache_d(uint64_t sourceid, uint64_t data[8], unsigned ch
|
||||
}
|
||||
}
|
||||
|
||||
void chipyard_simif_t::tcm_a(uint64_t address, uint64_t data, uint32_t mask, uint32_t opcode, uint32_t size) {
|
||||
bool load = opcode == 4;
|
||||
uint64_t rdata = 0;
|
||||
memcpy(&rdata, tcm + address - tcm_base, 8);
|
||||
tcm_q.push_back(rdata);
|
||||
|
||||
if (!load) {
|
||||
for (size_t i = 0; i < 8; i++) {
|
||||
if ((mask >> i) & 1) {
|
||||
memcpy(tcm + address - tcm_base + i, ((uint8_t*)&data) + i, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool chipyard_simif_t::tcm_d(uint64_t* data) {
|
||||
if (tcm_q.size() == 0)
|
||||
return false;
|
||||
*data = tcm_q[0];
|
||||
tcm_q.erase(tcm_q.begin());
|
||||
return true;
|
||||
}
|
||||
|
||||
#define parse_nibble(c) ((c) >= 'a' ? (c)-'a'+10 : (c)-'0')
|
||||
void chipyard_simif_t::loadmem(const char* fname) {
|
||||
std::ifstream in(fname);
|
||||
std::string line;
|
||||
if (!in.is_open()) {
|
||||
printf("SpikeTile couldn't open loadmem file %s\n", fname);
|
||||
abort();
|
||||
}
|
||||
size_t fsize = 0;
|
||||
size_t start = 0;
|
||||
while (std::getline(in, line)) {
|
||||
for (ssize_t i = line.length()-2, j = 0; i >= 0; i -= 2, j++) {
|
||||
char byte = (parse_nibble(line[i]) << 4) | parse_nibble(line[i+1]);
|
||||
ssize_t addr = (start + j) % tcm_size;
|
||||
tcm[addr] = (uint8_t)byte;
|
||||
}
|
||||
start += line.length()/2;
|
||||
fsize += line.length()/2;
|
||||
|
||||
if (fsize > tcm_size) {
|
||||
fprintf(stderr, "Loadmem file is too large\n");
|
||||
abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool insn_should_fence(uint64_t bits) {
|
||||
uint8_t opcode = bits & 0x7f;
|
||||
return opcode == 0b0101111 || opcode == 0b0001111;
|
||||
}
|
||||
|
||||
bool insn_is_wfi(uint64_t bits) {
|
||||
return bits == 0x10500073;
|
||||
}
|
||||
|
||||
void spike_thread_main(void* arg)
|
||||
{
|
||||
tile_t* tile = (tile_t*) arg;
|
||||
processor_t* proc = tile->proc;
|
||||
chipyard_simif_t* simif = tile->simif;
|
||||
state_t* state = proc->get_state();
|
||||
while (true) {
|
||||
while (tile->max_insns == 0) {
|
||||
host->switch_to();
|
||||
}
|
||||
while (tile->max_insns != 0) {
|
||||
// TODO: Fences don't work
|
||||
// uint64_t last_bits = tile->proc->get_last_bits();
|
||||
// if (insn_should_fence(last_bits) && !tile->simif->stq_empty()) {
|
||||
//uint64_t last_bits = proc->get_last_bits();
|
||||
// if (insn_should_fence(last_bits) && !simif->stq_empty()) {
|
||||
// host->switch_to();
|
||||
// }
|
||||
tile->proc->step(1);
|
||||
proc->step(1);
|
||||
tile->max_insns--;
|
||||
tile->proc->get_state()->mcycle->write(tile->simif->cycle);
|
||||
if (proc->is_waiting_for_interrupt()) {
|
||||
if (simif->fast_clint) {
|
||||
// uint64_t mip = state->mip->read();
|
||||
// uint64_t mie = state->mie->read();
|
||||
//printf("Setting MTIP %x %x %x %x %lx\n", simif->cycle, old_minstret, mip, mie,
|
||||
// state->pc);
|
||||
state->mip->backdoor_write_with_mask(MIP_MTIP, MIP_MTIP);
|
||||
tile->max_insns = tile->max_insns <= 1 ? 0 : 1;
|
||||
} else {
|
||||
//printf("SpikeTile in WFI\n");
|
||||
tile->max_insns = 0;
|
||||
}
|
||||
}
|
||||
if (tile->max_insns % 100 == 0) {
|
||||
uint64_t old_minstret = state->minstret->read();
|
||||
uint64_t tohost_addr = simif->htif ? simif->htif->get_tohost_addr() : 0;
|
||||
uint64_t fromhost_addr = simif->htif ? simif->htif->get_fromhost_addr() : 0;
|
||||
auto& mem_read = state->log_mem_read;
|
||||
reg_t mem_read_addr = mem_read.empty() ? 0 : std::get<0>(mem_read[0]);
|
||||
if ((old_minstret == state->minstret->read()) ||
|
||||
(tohost_addr && mem_read_addr == tohost_addr) ||
|
||||
(fromhost_addr && mem_read_addr == fromhost_addr)) {
|
||||
tile->max_insns == 0;
|
||||
}
|
||||
}
|
||||
state->mcycle->write(simif->cycle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@ import "DPI-C" function void spike_tile(input int hartid,
|
||||
input string executable,
|
||||
input int icache_sourceids,
|
||||
input int dcache_sourceids,
|
||||
input longint tcm_base,
|
||||
input longint tcm_size,
|
||||
input longint reset_vector,
|
||||
input longint ipc,
|
||||
input longint cycle,
|
||||
@@ -89,7 +91,18 @@ import "DPI-C" function void spike_tile(input int hartid,
|
||||
output int mmio_a_size,
|
||||
|
||||
input bit mmio_d_valid,
|
||||
input longint mmio_d_data
|
||||
input longint mmio_d_data,
|
||||
|
||||
input bit tcm_a_valid,
|
||||
input longint tcm_a_address,
|
||||
input longint tcm_a_data,
|
||||
input int tcm_a_mask,
|
||||
input int tcm_a_opcode,
|
||||
input int tcm_a_size,
|
||||
|
||||
output bit tcm_d_valid,
|
||||
input bit tcm_d_ready,
|
||||
output longint tcm_d_data
|
||||
);
|
||||
|
||||
|
||||
@@ -106,7 +119,9 @@ module SpikeBlackBox #(
|
||||
parameter READONLY_UNCACHEABLE,
|
||||
parameter EXECUTABLE,
|
||||
parameter ICACHE_SOURCEIDS,
|
||||
parameter DCACHE_SOURCEIDS )(
|
||||
parameter DCACHE_SOURCEIDS,
|
||||
parameter TCM_BASE,
|
||||
parameter TCM_SIZE)(
|
||||
input clock,
|
||||
input reset,
|
||||
input [63:0] reset_vector,
|
||||
@@ -185,7 +200,18 @@ module SpikeBlackBox #(
|
||||
output [31:0] mmio_a_size,
|
||||
|
||||
input mmio_d_valid,
|
||||
input [63:0] mmio_d_data
|
||||
input [63:0] mmio_d_data,
|
||||
|
||||
input tcm_a_valid,
|
||||
input [63:0] tcm_a_address,
|
||||
input [63:0] tcm_a_data,
|
||||
input [31:0] tcm_a_mask,
|
||||
input [31:0] tcm_a_opcode,
|
||||
input [31:0] tcm_a_size,
|
||||
|
||||
output tcm_d_valid,
|
||||
input tcm_d_ready,
|
||||
output [63:0] tcm_d_data
|
||||
);
|
||||
|
||||
longint __insns_retired;
|
||||
@@ -257,7 +283,13 @@ module SpikeBlackBox #(
|
||||
reg [63:0] __dcache_c_data_6_reg;
|
||||
reg [63:0] __dcache_c_data_7_reg;
|
||||
|
||||
|
||||
wire __tcm_d_ready;
|
||||
bit __tcm_d_valid;
|
||||
longint __tcm_d_data;
|
||||
|
||||
reg __tcm_d_valid_reg;
|
||||
reg [63:0] __tcm_d_data_reg;
|
||||
|
||||
|
||||
|
||||
always @(posedge clock) begin
|
||||
@@ -322,12 +354,18 @@ module SpikeBlackBox #(
|
||||
__dcache_c_data_6_reg <= 64'h0;
|
||||
__dcache_c_data_7 = 64'h0;
|
||||
__dcache_c_data_7_reg <= 64'h0;
|
||||
|
||||
__tcm_d_valid = 1'b0;
|
||||
__tcm_d_valid_reg <= 1'b0;
|
||||
__tcm_d_data = 64'h0;
|
||||
__tcm_d_data_reg <= 64'h0;
|
||||
spike_tile_reset(HARTID);
|
||||
end else begin
|
||||
spike_tile(HARTID, ISA, PMPREGIONS,
|
||||
ICACHE_SETS, ICACHE_WAYS, DCACHE_SETS, DCACHE_WAYS,
|
||||
CACHEABLE, UNCACHEABLE, READONLY_UNCACHEABLE, EXECUTABLE,
|
||||
ICACHE_SOURCEIDS, DCACHE_SOURCEIDS,
|
||||
TCM_BASE, TCM_SIZE,
|
||||
reset_vector, ipc, cycle, __insns_retired,
|
||||
debug, mtip, msip, meip, seip,
|
||||
|
||||
@@ -350,7 +388,10 @@ module SpikeBlackBox #(
|
||||
dcache_d_data_4, dcache_d_data_5, dcache_d_data_6, dcache_d_data_7,
|
||||
|
||||
__mmio_a_ready, __mmio_a_valid, __mmio_a_address, __mmio_a_data, __mmio_a_store, __mmio_a_size,
|
||||
mmio_d_valid, mmio_d_data
|
||||
mmio_d_valid, mmio_d_data,
|
||||
|
||||
tcm_a_valid, tcm_a_address, tcm_a_data, tcm_a_mask, tcm_a_opcode, tcm_a_size,
|
||||
__tcm_d_valid, __tcm_d_ready, __tcm_d_data
|
||||
);
|
||||
__insns_retired_reg <= __insns_retired;
|
||||
|
||||
@@ -385,6 +426,10 @@ module SpikeBlackBox #(
|
||||
__mmio_a_data_reg <= __mmio_a_data;
|
||||
__mmio_a_store_reg <= __mmio_a_store;
|
||||
__mmio_a_size_reg <= __mmio_a_size;
|
||||
|
||||
__tcm_d_valid_reg <= __tcm_d_valid;
|
||||
__tcm_d_data_reg <= __tcm_d_data;
|
||||
|
||||
end
|
||||
end // always @ (posedge clock)
|
||||
assign insns_retired = __insns_retired_reg;
|
||||
@@ -424,6 +469,8 @@ module SpikeBlackBox #(
|
||||
assign mmio_a_size = __mmio_a_size_reg;
|
||||
assign __mmio_a_ready = mmio_a_ready;
|
||||
|
||||
|
||||
assign tcm_d_valid = __tcm_d_valid_reg;
|
||||
assign tcm_d_data = __tcm_d_data_reg;
|
||||
assign __tcm_d_ready = tcm_d_ready;
|
||||
|
||||
endmodule;
|
||||
|
||||
@@ -15,8 +15,7 @@ import freechips.rocketchip.util._
|
||||
import freechips.rocketchip.tile._
|
||||
import freechips.rocketchip.prci.ClockSinkParameters
|
||||
|
||||
case class SpikeCoreParams(
|
||||
) extends CoreParams {
|
||||
case class SpikeCoreParams() extends CoreParams {
|
||||
val useVM = true
|
||||
val useHypervisor = false
|
||||
val useSupervisor = true
|
||||
@@ -79,7 +78,8 @@ case class SpikeTileParams(
|
||||
hartId: Int = 0,
|
||||
val core: SpikeCoreParams = SpikeCoreParams(),
|
||||
icacheParams: ICacheParams = ICacheParams(nWays = 32),
|
||||
dcacheParams: DCacheParams = DCacheParams(nWays = 32)
|
||||
dcacheParams: DCacheParams = DCacheParams(nWays = 32),
|
||||
tcmParams: Option[MasterPortParams] = None // tightly coupled memory
|
||||
) extends InstantiableTileParams[SpikeTile]
|
||||
{
|
||||
val name = Some("spike_tile")
|
||||
@@ -145,6 +145,27 @@ class SpikeTile(
|
||||
sourceId = IdRange(0, 1),
|
||||
requestFifo = true))))))
|
||||
|
||||
tlSlaveXbar.node :*= slaveNode
|
||||
val tcmNode = spikeTileParams.tcmParams.map { tcmP =>
|
||||
val device = new MemoryDevice
|
||||
val base = AddressSet.misaligned(tcmP.base, tcmP.size)
|
||||
val tcmNode = TLManagerNode(Seq(TLSlavePortParameters.v1(
|
||||
managers = Seq(TLSlaveParameters.v1(
|
||||
address = base,
|
||||
resources = device.reg,
|
||||
regionType = RegionType.IDEMPOTENT, // not cacheable
|
||||
executable = true,
|
||||
supportsGet = TransferSizes(1, 8),
|
||||
supportsPutFull = TransferSizes(1, 8),
|
||||
supportsPutPartial = TransferSizes(1, 8),
|
||||
fifoId = Some(0)
|
||||
)),
|
||||
beatBytes = 8
|
||||
)))
|
||||
connectTLSlave(tcmNode := TLBuffer(), 8)
|
||||
tcmNode
|
||||
}
|
||||
|
||||
tlOtherMastersNode := TLBuffer() := tlMasterXbar.node
|
||||
masterNode :=* tlOtherMastersNode
|
||||
tlMasterXbar.node := TLWidthWidget(64) := TLBuffer():= icacheNode
|
||||
@@ -166,7 +187,9 @@ class SpikeBlackBox(
|
||||
cacheable_regions: String,
|
||||
uncacheable_regions: String,
|
||||
readonly_uncacheable_regions: String,
|
||||
executable_regions: String) extends BlackBox(Map(
|
||||
executable_regions: String,
|
||||
tcm_base: BigInt,
|
||||
tcm_size: BigInt) extends BlackBox(Map(
|
||||
"HARTID" -> IntParam(hartId),
|
||||
"ISA" -> StringParam(isa),
|
||||
"PMPREGIONS" -> IntParam(pmpregions),
|
||||
@@ -179,7 +202,9 @@ class SpikeBlackBox(
|
||||
"UNCACHEABLE" -> StringParam(uncacheable_regions),
|
||||
"READONLY_UNCACHEABLE" -> StringParam(readonly_uncacheable_regions),
|
||||
"CACHEABLE" -> StringParam(cacheable_regions),
|
||||
"EXECUTABLE" -> StringParam(executable_regions)
|
||||
"EXECUTABLE" -> StringParam(executable_regions),
|
||||
"TCM_BASE" -> IntParam(tcm_base),
|
||||
"TCM_SIZE" -> IntParam(tcm_size)
|
||||
)) with HasBlackBoxResource {
|
||||
|
||||
val io = IO(new Bundle {
|
||||
@@ -258,6 +283,22 @@ class SpikeBlackBox(
|
||||
val data = Input(UInt(64.W))
|
||||
}
|
||||
}
|
||||
|
||||
val tcm = new Bundle {
|
||||
val a = new Bundle {
|
||||
val valid = Input(Bool())
|
||||
val address = Input(UInt(64.W))
|
||||
val data = Input(UInt(64.W))
|
||||
val mask = Input(UInt(32.W))
|
||||
val opcode = Input(UInt(32.W))
|
||||
val size = Input(UInt(32.W))
|
||||
}
|
||||
val d = new Bundle {
|
||||
val valid = Output(Bool())
|
||||
val ready = Input(Bool())
|
||||
val data = Output(UInt(64.W))
|
||||
}
|
||||
}
|
||||
})
|
||||
addResource("/vsrc/spiketile.v")
|
||||
addResource("/csrc/spiketile.cc")
|
||||
@@ -289,7 +330,10 @@ class SpikeTileModuleImp(outer: SpikeTile) extends BaseTileModuleImp(outer) {
|
||||
tileParams.icache.get.nSets, tileParams.icache.get.nWays,
|
||||
tileParams.dcache.get.nSets, tileParams.dcache.get.nWays,
|
||||
tileParams.dcache.get.nMSHRs,
|
||||
cacheable_regions, uncacheable_regions, readonly_uncacheable_regions, executable_regions))
|
||||
cacheable_regions, uncacheable_regions, readonly_uncacheable_regions, executable_regions,
|
||||
outer.spikeTileParams.tcmParams.map(_.base).getOrElse(0),
|
||||
outer.spikeTileParams.tcmParams.map(_.size).getOrElse(0)
|
||||
))
|
||||
spike.io.clock := clock.asBool
|
||||
val cycle = RegInit(0.U(64.W))
|
||||
cycle := cycle + 1.U
|
||||
@@ -304,64 +348,63 @@ class SpikeTileModuleImp(outer: SpikeTile) extends BaseTileModuleImp(outer) {
|
||||
spike.io.msip := int_bundle.msip
|
||||
spike.io.meip := int_bundle.meip
|
||||
spike.io.seip := int_bundle.seip.get
|
||||
spike.io.ipc := PlusArg("spike-ipc", 10000, width=64)
|
||||
spike.io.ipc := PlusArg("spike-ipc", width=32, default=10000)
|
||||
|
||||
val blockBits = log2Ceil(p(CacheBlockBytes))
|
||||
|
||||
val icache_a_q = Module(new Queue(new TLBundleA(icacheEdge.bundle), 1, flow=true, pipe=true))
|
||||
spike.io.icache.a.ready := icache_a_q.io.enq.ready && icache_a_q.io.count === 0.U
|
||||
icache_tl.a <> icache_a_q.io.deq
|
||||
icache_a_q.io.enq.valid := spike.io.icache.a.valid
|
||||
icache_a_q.io.enq.bits := icacheEdge.Get(
|
||||
spike.io.icache.a.ready := icache_tl.a.ready
|
||||
icache_tl.a.valid := spike.io.icache.a.valid
|
||||
icache_tl.a.bits := icacheEdge.Get(
|
||||
fromSource = spike.io.icache.a.sourceid,
|
||||
toAddress = (spike.io.icache.a.address >> blockBits) << blockBits,
|
||||
lgSize = blockBits.U)._2
|
||||
|
||||
icache_tl.d.ready := true.B
|
||||
spike.io.icache.d.valid := icache_tl.d.valid
|
||||
spike.io.icache.d.sourceid := icache_tl.d.bits.source
|
||||
spike.io.icache.d.data := icache_tl.d.bits.data.asTypeOf(Vec(8, UInt(64.W)))
|
||||
|
||||
val dcache_a_q = Module(new Queue(new TLBundleA(dcacheEdge.bundle), 1, flow=true, pipe=true))
|
||||
spike.io.dcache.a.ready := dcache_a_q.io.enq.ready && dcache_a_q.io.count === 0.U
|
||||
dcache_tl.a <> dcache_a_q.io.deq
|
||||
dcache_a_q.io.enq.valid := spike.io.dcache.a.valid
|
||||
dcache_a_q.io.enq.bits := dcacheEdge.AcquireBlock(
|
||||
fromSource = spike.io.dcache.a.sourceid,
|
||||
toAddress = (spike.io.dcache.a.address >> blockBits) << blockBits,
|
||||
lgSize = blockBits.U,
|
||||
growPermissions = Mux(spike.io.dcache.a.state_old, 2.U, Mux(spike.io.dcache.a.state_new, 1.U, 0.U)))._2
|
||||
|
||||
spike.io.dcache.a.ready := dcache_tl.a.ready
|
||||
dcache_tl.a.valid := spike.io.dcache.a.valid
|
||||
if (dcacheEdge.manager.anySupportAcquireB) {
|
||||
dcache_tl.a.bits := dcacheEdge.AcquireBlock(
|
||||
fromSource = spike.io.dcache.a.sourceid,
|
||||
toAddress = (spike.io.dcache.a.address >> blockBits) << blockBits,
|
||||
lgSize = blockBits.U,
|
||||
growPermissions = Mux(spike.io.dcache.a.state_old, 2.U, Mux(spike.io.dcache.a.state_new, 1.U, 0.U)))._2
|
||||
} else {
|
||||
dcache_tl.a.bits := DontCare
|
||||
}
|
||||
dcache_tl.b.ready := true.B
|
||||
spike.io.dcache.b.valid := dcache_tl.b.valid
|
||||
spike.io.dcache.b.address := dcache_tl.b.bits.address
|
||||
spike.io.dcache.b.source := dcache_tl.b.bits.source
|
||||
spike.io.dcache.b.param := dcache_tl.b.bits.param
|
||||
|
||||
val dcache_c_q = Module(new Queue(new TLBundleC(dcacheEdge.bundle), 1, flow=true, pipe=true))
|
||||
spike.io.dcache.c.ready := dcache_c_q.io.enq.ready && dcache_c_q.io.count === 0.U
|
||||
dcache_tl.c <> dcache_c_q.io.deq
|
||||
dcache_c_q.io.enq.valid := spike.io.dcache.c.valid
|
||||
dcache_c_q.io.enq.bits := Mux(spike.io.dcache.c.voluntary,
|
||||
dcacheEdge.Release(
|
||||
fromSource = spike.io.dcache.c.sourceid,
|
||||
toAddress = spike.io.dcache.c.address,
|
||||
lgSize = blockBits.U,
|
||||
shrinkPermissions = spike.io.dcache.c.param,
|
||||
data = spike.io.dcache.c.data.asUInt)._2,
|
||||
Mux(spike.io.dcache.c.has_data,
|
||||
dcacheEdge.ProbeAck(
|
||||
spike.io.dcache.c.ready := dcache_tl.c.ready
|
||||
dcache_tl.c.valid := spike.io.dcache.c.valid
|
||||
if (dcacheEdge.manager.anySupportAcquireB) {
|
||||
dcache_tl.c.bits := Mux(spike.io.dcache.c.voluntary,
|
||||
dcacheEdge.Release(
|
||||
fromSource = spike.io.dcache.c.sourceid,
|
||||
toAddress = spike.io.dcache.c.address,
|
||||
lgSize = blockBits.U,
|
||||
reportPermissions = spike.io.dcache.c.param,
|
||||
data = spike.io.dcache.c.data.asUInt),
|
||||
dcacheEdge.ProbeAck(
|
||||
fromSource = spike.io.dcache.c.sourceid,
|
||||
toAddress = spike.io.dcache.c.address,
|
||||
lgSize = blockBits.U,
|
||||
reportPermissions = spike.io.dcache.c.param)
|
||||
))
|
||||
shrinkPermissions = spike.io.dcache.c.param,
|
||||
data = spike.io.dcache.c.data.asUInt)._2,
|
||||
Mux(spike.io.dcache.c.has_data,
|
||||
dcacheEdge.ProbeAck(
|
||||
fromSource = spike.io.dcache.c.sourceid,
|
||||
toAddress = spike.io.dcache.c.address,
|
||||
lgSize = blockBits.U,
|
||||
reportPermissions = spike.io.dcache.c.param,
|
||||
data = spike.io.dcache.c.data.asUInt),
|
||||
dcacheEdge.ProbeAck(
|
||||
fromSource = spike.io.dcache.c.sourceid,
|
||||
toAddress = spike.io.dcache.c.address,
|
||||
lgSize = blockBits.U,
|
||||
reportPermissions = spike.io.dcache.c.param)
|
||||
))
|
||||
} else {
|
||||
dcache_tl.c.bits := DontCare
|
||||
}
|
||||
|
||||
val has_data = dcacheEdge.hasData(dcache_tl.d.bits)
|
||||
val should_finish = dcacheEdge.isRequest(dcache_tl.d.bits)
|
||||
@@ -376,12 +419,10 @@ class SpikeTileModuleImp(outer: SpikeTile) extends BaseTileModuleImp(outer) {
|
||||
dcache_tl.e.valid := dcache_tl.d.valid && should_finish
|
||||
dcache_tl.e.bits := dcacheEdge.GrantAck(dcache_tl.d.bits)
|
||||
|
||||
val mmio_a_q = Module(new Queue(new TLBundleA(mmioEdge.bundle), 1, flow=true, pipe=true))
|
||||
spike.io.mmio.a.ready := mmio_a_q.io.enq.ready && mmio_a_q.io.count === 0.U
|
||||
mmio_tl.a <> mmio_a_q.io.deq
|
||||
mmio_a_q.io.enq.valid := spike.io.mmio.a.valid
|
||||
spike.io.mmio.a.ready := mmio_tl.a.ready
|
||||
mmio_tl.a.valid := spike.io.mmio.a.valid
|
||||
val log_size = MuxCase(0.U, (0 until 3).map { i => (spike.io.mmio.a.size === (1 << i).U) -> i.U })
|
||||
mmio_a_q.io.enq.bits := Mux(spike.io.mmio.a.store,
|
||||
mmio_tl.a.bits := Mux(spike.io.mmio.a.store,
|
||||
mmioEdge.Put(0.U, spike.io.mmio.a.address, log_size, spike.io.mmio.a.data)._2,
|
||||
mmioEdge.Get(0.U, spike.io.mmio.a.address, log_size)._2)
|
||||
|
||||
@@ -389,9 +430,33 @@ class SpikeTileModuleImp(outer: SpikeTile) extends BaseTileModuleImp(outer) {
|
||||
spike.io.mmio.d.valid := mmio_tl.d.valid
|
||||
spike.io.mmio.d.data := mmio_tl.d.bits.data
|
||||
|
||||
spike.io.tcm := DontCare
|
||||
spike.io.tcm.a.valid := false.B
|
||||
spike.io.tcm.d.ready := true.B
|
||||
outer.tcmNode.map { tcmNode =>
|
||||
val (tcm_tl, tcmEdge) = tcmNode.in(0)
|
||||
val debug_tcm_tl = WireInit(tcm_tl)
|
||||
dontTouch(debug_tcm_tl)
|
||||
tcm_tl.a.ready := true.B
|
||||
spike.io.tcm.a.valid := tcm_tl.a.valid
|
||||
spike.io.tcm.a.address := tcm_tl.a.bits.address
|
||||
spike.io.tcm.a.data := tcm_tl.a.bits.data
|
||||
spike.io.tcm.a.mask := tcm_tl.a.bits.mask
|
||||
spike.io.tcm.a.opcode := tcm_tl.a.bits.opcode
|
||||
spike.io.tcm.a.size := tcm_tl.a.bits.size
|
||||
|
||||
spike.io.tcm.d.ready := tcm_tl.d.ready
|
||||
tcm_tl.d.bits := tcmEdge.AccessAck(RegNext(tcm_tl.a.bits))
|
||||
when (RegNext(tcm_tl.a.bits.opcode === TLMessages.Get)) {
|
||||
tcm_tl.d.bits.opcode := TLMessages.AccessAckData
|
||||
}
|
||||
tcm_tl.d.valid := spike.io.tcm.d.valid
|
||||
tcm_tl.d.bits.data := spike.io.tcm.d.data
|
||||
}
|
||||
}
|
||||
|
||||
class WithNSpikeCores(n: Int = 1, overrideIdOffset: Option[Int] = None) extends Config((site, here, up) => {
|
||||
class WithNSpikeCores(n: Int = 1, tileParams: SpikeTileParams = SpikeTileParams(),
|
||||
overrideIdOffset: Option[Int] = None) extends Config((site, here, up) => {
|
||||
case TilesLocated(InSubsystem) => {
|
||||
// Calculate the next available hart ID (since hart ID cannot be duplicated)
|
||||
val prev = up(TilesLocated(InSubsystem), site)
|
||||
@@ -399,8 +464,21 @@ class WithNSpikeCores(n: Int = 1, overrideIdOffset: Option[Int] = None) extends
|
||||
// Create TileAttachParams for every core to be instantiated
|
||||
(0 until n).map { i =>
|
||||
SpikeTileAttachParams(
|
||||
tileParams = SpikeTileParams(hartId = i + idOffset)
|
||||
tileParams = tileParams.copy(hartId = i + idOffset)
|
||||
)
|
||||
} ++ prev
|
||||
}
|
||||
})
|
||||
|
||||
class WithSpikeTCM extends Config((site, here, up) => {
|
||||
case TilesLocated(InSubsystem) => {
|
||||
val prev = up(TilesLocated(InSubsystem))
|
||||
require(prev.size == 1)
|
||||
val spike = prev(0).asInstanceOf[SpikeTileAttachParams]
|
||||
Seq(spike.copy(tileParams = spike.tileParams.copy(
|
||||
tcmParams = Some(up(ExtMem).get.master)
|
||||
)))
|
||||
}
|
||||
case ExtMem => None
|
||||
case BankedL2Key => up(BankedL2Key).copy(nBanks = 0)
|
||||
})
|
||||
|
||||
@@ -12,6 +12,7 @@ import freechips.rocketchip.prci._
|
||||
import freechips.rocketchip.config.{Field, Parameters}
|
||||
import freechips.rocketchip.devices.tilelink._
|
||||
import freechips.rocketchip.devices.debug.{HasPeripheryDebug, HasPeripheryDebugModuleImp, ExportDebug, DebugModuleKey}
|
||||
import sifive.blocks.devices.uart.{HasPeripheryUART, PeripheryUARTKey}
|
||||
import freechips.rocketchip.diplomacy._
|
||||
import freechips.rocketchip.tile._
|
||||
import freechips.rocketchip.tilelink._
|
||||
@@ -45,9 +46,33 @@ trait CanHaveHTIF { this: BaseSubsystem =>
|
||||
}
|
||||
}
|
||||
|
||||
// This trait adds the "chosen" node to DTS, which
|
||||
// can be used to pass information to OS about the earlycon
|
||||
case object ChosenInDTS extends Field[Boolean](true)
|
||||
trait CanHaveChosenInDTS { this: BaseSubsystem =>
|
||||
if (p(ChosenInDTS)) {
|
||||
this match {
|
||||
case t: HasPeripheryUART if (!p(PeripheryUARTKey).isEmpty) => {
|
||||
val chosen = new Device {
|
||||
def describe(resources: ResourceBindings): Description = {
|
||||
val stdout = resources("stdout").map(_.value)
|
||||
Description("chosen", resources("uart").headOption.map { case Binding(_, value) =>
|
||||
"stdout-path" -> Seq(value)
|
||||
}.toMap)
|
||||
}
|
||||
}
|
||||
ResourceBinding {
|
||||
t.uarts.foreach(u => Resource(chosen, "uart").bind(ResourceAlias(u.device.label)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ChipyardSubsystem(implicit p: Parameters) extends BaseSubsystem
|
||||
with HasTiles
|
||||
with CanHaveHTIF
|
||||
with CanHaveChosenInDTS
|
||||
{
|
||||
def coreMonitorBundles = tiles.map {
|
||||
case r: RocketTile => r.module.core.rocketImpl.coreMonitorBundle
|
||||
|
||||
@@ -60,4 +60,5 @@ class AbstractConfig extends Config(
|
||||
new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++ // no external interrupts
|
||||
new freechips.rocketchip.subsystem.WithDontDriveBusClocksFromSBus ++ // leave the bus clocks undriven by sbus
|
||||
new freechips.rocketchip.subsystem.WithCoherentBusTopology ++ // hierarchical buses including sbus/mbus/pbus/fbus/cbus/l2
|
||||
new freechips.rocketchip.subsystem.WithDTS("ucb-bar,chipyard", Nil) ++ // custom device name for DTS
|
||||
new freechips.rocketchip.system.BaseConfig) // "base" rocketchip system
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package chipyard
|
||||
|
||||
import freechips.rocketchip.config.{Config}
|
||||
import freechips.rocketchip.rocket.{DCacheParams}
|
||||
|
||||
// Configs which instantiate a Spike-simulated
|
||||
// tile that interacts with the Chipyard SoC
|
||||
@@ -14,6 +15,33 @@ class SpikeConfig extends Config(
|
||||
class SpikeFastUARTConfig extends Config(
|
||||
new chipyard.WithNSpikeCores(1) ++
|
||||
new chipyard.config.WithUARTFIFOEntries(128, 128) ++
|
||||
new chipyard.config.WithMemoryBusFrequency(1) ++
|
||||
new chipyard.config.WithPeripheryBusFrequency(1) ++
|
||||
new chipyard.config.WithMemoryBusFrequency(2) ++
|
||||
new chipyard.config.WithPeripheryBusFrequency(2) ++
|
||||
new chipyard.config.AbstractConfig)
|
||||
|
||||
// Makes the UART fast, also builds no L2 and a ludicrous L1D
|
||||
class SpikeUltraFastConfig extends Config(
|
||||
new chipyard.WithSpikeTCM ++
|
||||
new chipyard.WithNSpikeCores(1) ++
|
||||
new testchipip.WithSerialPBusMem ++
|
||||
new chipyard.config.WithUARTFIFOEntries(128, 128) ++
|
||||
new chipyard.config.WithMemoryBusFrequency(2) ++
|
||||
new chipyard.config.WithPeripheryBusFrequency(2) ++
|
||||
new chipyard.config.WithBroadcastManager ++
|
||||
new chipyard.config.AbstractConfig)
|
||||
|
||||
// Add the default firechip devices
|
||||
class SpikeUltraFastDevicesConfig extends Config(
|
||||
new chipyard.harness.WithSimBlockDevice ++
|
||||
new chipyard.harness.WithLoopbackNIC ++
|
||||
new icenet.WithIceNIC ++
|
||||
new testchipip.WithBlockDevice ++
|
||||
|
||||
new chipyard.WithSpikeTCM ++
|
||||
new chipyard.WithNSpikeCores(1) ++
|
||||
new testchipip.WithSerialPBusMem ++
|
||||
new chipyard.config.WithUARTFIFOEntries(128, 128) ++
|
||||
new chipyard.config.WithMemoryBusFrequency(2) ++
|
||||
new chipyard.config.WithPeripheryBusFrequency(2) ++
|
||||
new chipyard.config.WithBroadcastManager ++
|
||||
new chipyard.config.AbstractConfig)
|
||||
|
||||
Submodule generators/gemmini updated: 686cb15dad...4dd19f3e93
Submodule generators/sifive-blocks updated: 4273925fdd...3938f301ce
Submodule software/firemarshal updated: 12784a42cb...fb93e3116f
@@ -6,7 +6,8 @@ LDFLAGS= -static
|
||||
include libgloss.mk
|
||||
|
||||
PROGRAMS = pwm blkdev accum charcount nic-loopback big-blkdev pingd \
|
||||
streaming-passthrough streaming-fir nvdla spiflashread spiflashwrite fft gcd
|
||||
streaming-passthrough streaming-fir nvdla spiflashread spiflashwrite fft gcd \
|
||||
hello
|
||||
|
||||
spiflash.img: spiflash.py
|
||||
python3 $<
|
||||
|
||||
6
tests/hello.c
Normal file
6
tests/hello.c
Normal file
@@ -0,0 +1,6 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main(void) {
|
||||
printf("Hello world\n");
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user