aboutsummaryrefslogtreecommitdiffstats
path: root/backends
diff options
context:
space:
mode:
authorEddie Hung <eddie@fpgeh.com>2019-05-02 10:44:59 -0700
committerEddie Hung <eddie@fpgeh.com>2019-05-02 10:44:59 -0700
commit5cd19b52da297cc7d44e9bf11dc9d1664a02ccce (patch)
tree6206a4fa059c47a56cc43914d4141a386a5f2c7f /backends
parent4aca928033874e8e35ecc4a18f22475c00bebad9 (diff)
parent98925f6c4be611434e75f0ccf645a7ef8adcfc63 (diff)
downloadyosys-5cd19b52da297cc7d44e9bf11dc9d1664a02ccce.tar.gz
yosys-5cd19b52da297cc7d44e9bf11dc9d1664a02ccce.tar.bz2
yosys-5cd19b52da297cc7d44e9bf11dc9d1664a02ccce.zip
Merge remote-tracking branch 'origin/master' into xc7mux
Diffstat (limited to 'backends')
-rw-r--r--backends/firrtl/firrtl.cc87
1 files changed, 62 insertions, 25 deletions
diff --git a/backends/firrtl/firrtl.cc b/backends/firrtl/firrtl.cc
index ed6e9f8ee..9feff71c6 100644
--- a/backends/firrtl/firrtl.cc
+++ b/backends/firrtl/firrtl.cc
@@ -163,31 +163,61 @@ struct FirrtlWorker
}
};
/* Memories defined within this module. */
- struct memory {
- string name; // memory name
- int abits; // number of address bits
- int size; // size (in units) of the memory
- int width; // size (in bits) of each element
- int read_latency;
- int write_latency;
- vector<read_port> read_ports;
- vector<write_port> write_ports;
- std::string init_file;
- std::string init_file_srcFileSpec;
- memory(string name, int abits, int size, int width) : name(name), abits(abits), size(size), width(width), read_latency(0), write_latency(1), init_file(""), init_file_srcFileSpec("") {}
- memory() : read_latency(0), write_latency(1), init_file(""), init_file_srcFileSpec(""){}
- void add_memory_read_port(read_port &rp) {
- read_ports.push_back(rp);
- }
- void add_memory_write_port(write_port &wp) {
- write_ports.push_back(wp);
- }
- void add_memory_file(std::string init_file, std::string init_file_srcFileSpec) {
- this->init_file = init_file;
- this->init_file_srcFileSpec = init_file_srcFileSpec;
+ struct memory {
+ Cell *pCell; // for error reporting
+ string name; // memory name
+ int abits; // number of address bits
+ int size; // size (in units) of the memory
+ int width; // size (in bits) of each element
+ int read_latency;
+ int write_latency;
+ vector<read_port> read_ports;
+ vector<write_port> write_ports;
+ std::string init_file;
+ std::string init_file_srcFileSpec;
+ string srcLine;
+ memory(Cell *pCell, string name, int abits, int size, int width) : pCell(pCell), name(name), abits(abits), size(size), width(width), read_latency(0), write_latency(1), init_file(""), init_file_srcFileSpec("") {
+ // Provide defaults for abits or size if one (but not the other) is specified.
+ if (this->abits == 0 && this->size != 0) {
+ this->abits = ceil_log2(this->size);
+ } else if (this->abits != 0 && this->size == 0) {
+ this->size = 1 << this->abits;
+ }
+ // Sanity-check this construction.
+ if (this->name == "") {
+ log_error("Nameless memory%s\n", this->atLine());
+ }
+ if (this->abits == 0 && this->size == 0) {
+ log_error("Memory %s has zero address bits and size%s\n", this->name.c_str(), this->atLine());
+ }
+ if (this->width == 0) {
+ log_error("Memory %s has zero width%s\n", this->name.c_str(), this->atLine());
+ }
}
+ // We need a default constructor for the dict insert.
+ memory() : pCell(0), read_latency(0), write_latency(1), init_file(""), init_file_srcFileSpec(""){}
+
+ const char *atLine() {
+ if (srcLine == "") {
+ if (pCell) {
+ auto p = pCell->attributes.find("\\src");
+ srcLine = " at " + p->second.decode_string();
+ }
+ }
+ return srcLine.c_str();
+ }
+ void add_memory_read_port(read_port &rp) {
+ read_ports.push_back(rp);
+ }
+ void add_memory_write_port(write_port &wp) {
+ write_ports.push_back(wp);
+ }
+ void add_memory_file(std::string init_file, std::string init_file_srcFileSpec) {
+ this->init_file = init_file;
+ this->init_file_srcFileSpec = init_file_srcFileSpec;
+ }
- };
+ };
dict<string, memory> memories;
void register_memory(memory &m)
@@ -604,7 +634,7 @@ struct FirrtlWorker
int abits = cell->parameters.at("\\ABITS").as_int();
int width = cell->parameters.at("\\WIDTH").as_int();
int size = cell->parameters.at("\\SIZE").as_int();
- memory m(mem_id, abits, size, width);
+ memory m(cell, mem_id, abits, size, width);
int rd_ports = cell->parameters.at("\\RD_PORTS").as_int();
int wr_ports = cell->parameters.at("\\WR_PORTS").as_int();
@@ -681,6 +711,8 @@ struct FirrtlWorker
{
std::string cell_type = fid(cell->type);
std::string mem_id = make_id(cell->parameters["\\MEMID"].decode_string());
+ int abits = cell->parameters.at("\\ABITS").as_int();
+ int width = cell->parameters.at("\\WIDTH").as_int();
memory *mp = nullptr;
if (cell->type == "$meminit" ) {
log_error("$meminit (%s.%s.%s) currently unsupported\n", log_id(module), log_id(cell), mem_id.c_str());
@@ -693,6 +725,11 @@ struct FirrtlWorker
Const clk_enable = cell->parameters.at("\\CLK_ENABLE");
Const clk_polarity = cell->parameters.at("\\CLK_POLARITY");
+ // Do we already have an entry for this memory?
+ if (memories.count(mem_id) == 0) {
+ memory m(cell, mem_id, abits, 0, width);
+ register_memory(m);
+ }
mp = &memories.at(mem_id);
int portNum = 0;
bool transparency = false;
@@ -890,7 +927,7 @@ struct FirrtlWorker
// If we have any memory definitions, output them.
for (auto kv : memories) {
- memory m = kv.second;
+ memory &m = kv.second;
f << stringf(" mem %s:\n", m.name.c_str());
f << stringf(" data-type => UInt<%d>\n", m.width);
f << stringf(" depth => %d\n", m.size);