forked from ucb-bar/riscv-mini
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
bf7c35a
commit 98235b5
Showing
5 changed files
with
403 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,8 +2,11 @@ generated-src | |
test_run_dir | ||
target | ||
project/target | ||
logs | ||
*.key | ||
*.log | ||
*.swp | ||
*.out | ||
.ivy2 | ||
VTile | ||
dump.vcd* | ||
DVEfiles |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
// See LICENSE for license details. | ||
|
||
#include "mm.h" | ||
#include <iostream> | ||
#include <fstream> | ||
#include <cstdlib> | ||
#include <cstring> | ||
#include <string> | ||
#include <cassert> | ||
|
||
mm_magic_t::mm_magic_t(size_t size, size_t word_size): | ||
data(new char[size]), | ||
size(size), | ||
word_size(word_size), | ||
store_inflight(false) | ||
{ | ||
dummy_data.resize(word_size); | ||
} | ||
|
||
mm_magic_t::~mm_magic_t() | ||
{ | ||
delete [] data; | ||
} | ||
|
||
void mm_magic_t::write(uint64_t addr, char *data) { | ||
addr %= this->size; | ||
|
||
char* base = this->data + addr; | ||
memcpy(base, data, word_size); | ||
} | ||
|
||
void mm_magic_t::write(uint64_t addr, char *data, uint64_t strb, uint64_t size) | ||
{ | ||
strb &= ((1L << size) - 1) << (addr % word_size); | ||
addr %= this->size; | ||
|
||
char *base = this->data + addr; | ||
for (int i = 0; i < word_size; i++) { | ||
if (strb & 1) base[i] = data[i]; | ||
strb >>= 1; | ||
} | ||
} | ||
|
||
std::vector<char> mm_magic_t::read(uint64_t addr) | ||
{ | ||
addr %= this->size; | ||
|
||
char *base = this->data + addr; | ||
return std::vector<char>(base, base + word_size); | ||
} | ||
|
||
void mm_magic_t::tick( | ||
bool reset, | ||
bool ar_valid, | ||
uint64_t ar_addr, | ||
uint64_t ar_id, | ||
uint64_t ar_size, | ||
uint64_t ar_len, | ||
|
||
bool aw_valid, | ||
uint64_t aw_addr, | ||
uint64_t aw_id, | ||
uint64_t aw_size, | ||
uint64_t aw_len, | ||
|
||
bool w_valid, | ||
uint64_t w_strb, | ||
void *w_data, | ||
bool w_last, | ||
|
||
bool r_ready, | ||
bool b_ready) | ||
{ | ||
bool ar_fire = !reset && ar_valid && ar_ready(); | ||
bool aw_fire = !reset && aw_valid && aw_ready(); | ||
bool w_fire = !reset && w_valid && w_ready(); | ||
bool r_fire = !reset && r_valid() && r_ready; | ||
bool b_fire = !reset && b_valid() && b_ready; | ||
|
||
if (ar_fire) { | ||
uint64_t start_addr = (ar_addr / word_size) * word_size; | ||
for (size_t i = 0; i <= ar_len; i++) { | ||
auto dat = read(start_addr + i * word_size); | ||
rresp.push(mm_rresp_t(ar_id, dat, i == ar_len)); | ||
} | ||
} | ||
|
||
if (aw_fire) { | ||
store_addr = aw_addr; | ||
store_id = aw_id; | ||
store_count = aw_len + 1; | ||
store_size = 1 << aw_size; | ||
store_inflight = true; | ||
} | ||
|
||
if (w_fire) { | ||
write(store_addr, (char*)w_data, w_strb, store_size); | ||
store_addr += store_size; | ||
store_count--; | ||
|
||
if (store_count == 0) { | ||
store_inflight = false; | ||
bresp.push(store_id); | ||
assert(w_last); | ||
} | ||
} | ||
|
||
if (b_fire) | ||
bresp.pop(); | ||
|
||
if (r_fire) | ||
rresp.pop(); | ||
|
||
cycle++; | ||
|
||
if (reset) { | ||
while (!bresp.empty()) bresp.pop(); | ||
while (!rresp.empty()) rresp.pop(); | ||
cycle = 0; | ||
} | ||
} | ||
|
||
void load_mem(char* mem, const char* fn) | ||
{ | ||
int start = 0; | ||
std::ifstream in(fn); | ||
if (!in) | ||
{ | ||
std::cerr << "could not open " << fn << std::endl; | ||
exit(EXIT_FAILURE); | ||
} | ||
|
||
std::string line; | ||
while (std::getline(in, line)) | ||
{ | ||
#define parse_nibble(c) ((c) >= 'a' ? (c)-'a'+10 : (c)-'0') | ||
for (int i = line.length()-2, j = 0; i >= 0; i -= 2, j++) { | ||
mem[start + j] = (parse_nibble(line[i]) << 4) | parse_nibble(line[i+1]); | ||
} | ||
start += line.length()/2; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
// See LICENSE for license details. | ||
|
||
#ifndef MM_EMULATOR_H | ||
#define MM_EMULATOR_H | ||
|
||
#include <stdint.h> | ||
#include <cstring> | ||
#include <queue> | ||
|
||
struct mm_rresp_t | ||
{ | ||
uint64_t id; | ||
std::vector<char> data; | ||
bool last; | ||
|
||
mm_rresp_t(uint64_t id, std::vector<char> data, bool last) | ||
{ | ||
this->id = id; | ||
this->data = data; | ||
this->last = last; | ||
} | ||
|
||
mm_rresp_t() | ||
{ | ||
this->id = 0; | ||
this->last = false; | ||
} | ||
}; | ||
|
||
class mm_magic_t | ||
{ | ||
public: | ||
mm_magic_t(size_t size, size_t word_size); | ||
~mm_magic_t(); | ||
void init(size_t sz, int word_size); | ||
char* get_data() { return data; } | ||
size_t get_size() { return size; } | ||
|
||
bool ar_ready() { return true; } | ||
bool aw_ready() { return !store_inflight; } | ||
bool w_ready() { return store_inflight; } | ||
bool b_valid() { return !bresp.empty(); } | ||
uint64_t b_resp() { return 0; } | ||
uint64_t b_id() { return b_valid() ? bresp.front() : 0; } | ||
bool r_valid() { return !rresp.empty(); } | ||
uint64_t r_resp() { return 0; } | ||
uint64_t r_id() { return r_valid() ? rresp.front().id: 0; } | ||
void *r_data() { return r_valid() ? &rresp.front().data[0] : &dummy_data[0]; } | ||
bool r_last() { return r_valid() ? rresp.front().last : false; } | ||
|
||
void tick | ||
( | ||
bool reset, | ||
|
||
bool ar_valid, | ||
uint64_t ar_addr, | ||
uint64_t ar_id, | ||
uint64_t ar_size, | ||
uint64_t ar_len, | ||
|
||
bool aw_valid, | ||
uint64_t aw_addr, | ||
uint64_t aw_id, | ||
uint64_t aw_size, | ||
uint64_t aw_len, | ||
|
||
bool w_valid, | ||
uint64_t w_strb, | ||
void *w_data, | ||
bool w_last, | ||
|
||
bool r_ready, | ||
bool b_ready | ||
); | ||
|
||
void write(uint64_t addr, char *data); | ||
void write(uint64_t addr, char *data, uint64_t strb, uint64_t size); | ||
std::vector<char> read(uint64_t addr); | ||
|
||
private: | ||
char* data; | ||
size_t size; | ||
size_t word_size; | ||
|
||
bool store_inflight; | ||
uint64_t store_addr; | ||
uint64_t store_id; | ||
uint64_t store_size; | ||
uint64_t store_count; | ||
std::vector<char> dummy_data; | ||
std::queue<uint64_t> bresp; | ||
|
||
std::queue<mm_rresp_t> rresp; | ||
|
||
uint64_t cycle; | ||
}; | ||
|
||
void load_mem(char* mem, const char* fn); | ||
#endif |
Oops, something went wrong.