aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTristan Gingold <tgingold@free.fr>2019-10-19 10:13:04 +0200
committerTristan Gingold <tgingold@free.fr>2019-10-19 10:13:04 +0200
commit2141001bc795cd4fd12c9bb3a0f5d689c7840ef5 (patch)
tree1b3781c0d23d10c1ff7205c0331e2a65c808fc46
parent0b29a7cb792bd07b112671a264defcb1085ba402 (diff)
downloadghdl-yosys-plugin-2141001bc795cd4fd12c9bb3a0f5d689c7840ef5.tar.gz
ghdl-yosys-plugin-2141001bc795cd4fd12c9bb3a0f5d689c7840ef5.tar.bz2
ghdl-yosys-plugin-2141001bc795cd4fd12c9bb3a0f5d689c7840ef5.zip
Initial support of memories.
-rw-r--r--src/ghdl.cc170
1 files changed, 152 insertions, 18 deletions
diff --git a/src/ghdl.cc b/src/ghdl.cc
index d6c3cba..d0c3c35 100644
--- a/src/ghdl.cc
+++ b/src/ghdl.cc
@@ -53,12 +53,21 @@ static std::string to_str(Sname name)
return res;
}
-static RTLIL::SigSpec get_src(std::vector<RTLIL::Wire *> &net_map, Net n)
+static Wire *get_wire(std::vector<RTLIL::Wire *> &net_map, Net n)
{
log_assert(n.id != 0);
// Search if N is the output of a cell.
Wire *res = n.id < net_map.size() ? net_map.at(n.id) : nullptr;
+ return res;
+}
+
+static RTLIL::SigSpec get_src(std::vector<RTLIL::Wire *> &net_map, Net n)
+{
+ log_assert(n.id != 0);
+
+ // Search if N is the output of a cell.
+ Wire *res = get_wire(net_map, n);
if (res != nullptr)
return res;
@@ -215,7 +224,6 @@ static RTLIL::SigSpec get_src(std::vector<RTLIL::Wire *> &net_map, Net n)
log_cmd_error("wire not found for %s\n", to_str(get_module_name(get_module(inst))).c_str());
break;
}
- return SigSpec();
}
static bool is_set(std::vector<RTLIL::Wire *> &net_map, Net n)
@@ -236,6 +244,107 @@ static void set_src(std::vector<RTLIL::Wire *> &net_map, Net n, Wire *wire)
net_map[n.id] = wire;
}
+static void import_memory(RTLIL::Module *module, std::vector<RTLIL::Wire *> &net_map, Instance inst)
+{
+ Input port_inp;
+ Instance port;
+ Net mem_o = get_output(inst, 0);
+ Net port_o;
+ unsigned prio = 0;
+ std::string mem_str = to_str(get_instance_name(inst));
+
+ // Memories appear only once.
+ log_assert(!is_set(net_map, mem_o));
+
+ // Create memory.
+ RTLIL::Memory *memory = new RTLIL::Memory;
+ memory->name = mem_str;
+
+ // Will be set later.
+ memory->width = 0;
+ memory->size = 0;
+ memory->start_offset = 0;
+
+ port_inp = get_first_sink(mem_o);
+ port = get_input_parent(port_inp);
+
+ // Add it to module.
+ module->memories[memory->name] = memory;
+
+ // TODO: initial value.
+
+ // Generate cells.
+ while (port_inp.id != 0) {
+ unsigned port_width;
+ unsigned port_abits;
+
+ port = get_input_parent(port_inp);
+ switch(get_id(port)) {
+ case Id_Mem_Rd:
+ {
+ Net o = get_output(port, 1);
+ port_width = get_width(o);
+ port_abits = get_width(get_input_net(port, 1));
+ RTLIL::Cell *cell = module->addCell(to_str(get_instance_name(port)), "$memrd");
+ RTLIL::Wire *wire = module->addWire(to_str(get_output_name(get_module(port), 1)), port_width);
+
+ cell->setPort("\\CLK", RTLIL::SigSpec(RTLIL::State::Sx, 1));
+ cell->setPort("\\EN", RTLIL::SigSpec(RTLIL::State::Sx, 1));
+ // Set laster in pass 2
+ // cell->setPort("\\ADDR", addr_sig);
+ cell->setPort("\\DATA", RTLIL::SigSpec(wire));
+
+ cell->parameters["\\MEMID"] = RTLIL::Const(mem_str);
+ cell->parameters["\\ABITS"] = RTLIL::Const(port_abits);
+ cell->parameters["\\WIDTH"] = RTLIL::Const(port_width);
+
+ cell->parameters["\\CLK_ENABLE"] = RTLIL::Const(0);
+ cell->parameters["\\CLK_POLARITY"] = RTLIL::Const(0);
+ cell->parameters["\\TRANSPARENT"] = RTLIL::Const(0);
+
+ set_src(net_map, o, wire);
+
+ port_o = get_output(port, 0);
+ set_src(net_map, port_o, reinterpret_cast<Wire*>(cell));
+ }
+ break;
+ case Id_Mem_Wr_Sync:
+ {
+ RTLIL::Cell *cell = module->addCell(to_str(get_instance_name(port)), "$memwr");
+
+ port_width = get_width(get_input_net(port, 4));
+ port_abits = get_width(get_input_net(port, 1));
+
+ // Set later: addr, data, clk, en
+
+ cell->parameters["\\MEMID"] = RTLIL::Const(mem_str);
+ cell->parameters["\\ABITS"] = RTLIL::Const(port_abits);
+ cell->parameters["\\WIDTH"] = RTLIL::Const(port_width);
+
+ cell->parameters["\\CLK_ENABLE"] = RTLIL::Const(1);
+ cell->parameters["\\CLK_POLARITY"] = RTLIL::Const(1);
+
+ cell->parameters["\\PRIORITY"] = RTLIL::Const(prio++);
+
+ port_o = get_output(port, 0);
+ set_src(net_map, port_o, reinterpret_cast<Wire*>(cell));
+ }
+ break;
+ default:
+ log_assert(0);
+ }
+
+ if (memory->width == 0) {
+ memory->width = port_width;
+ memory->size = get_width(mem_o) / memory->width;
+ } else {
+ log_assert(port_width == (unsigned)memory->width);
+ }
+
+ port_inp = get_first_sink(port_o);
+ }
+}
+
static void import_module(RTLIL::Design *design, GhdlSynth::Module m)
{
std::string module_name = to_str(get_module_name(m));
@@ -261,23 +370,23 @@ static void import_module(RTLIL::Design *design, GhdlSynth::Module m)
if (!is_valid(self_inst)) { // blackbox
module->set_bool_attribute("\\blackbox");
- Port_Idx nbr_inputs = get_nbr_inputs(m);
- for (Port_Idx idx = 0; idx < nbr_inputs; idx++) {
- RTLIL::Wire *wire = module->addWire(
- to_str(get_input_name(m, idx)),
- get_input_width(m, idx));
- wire->port_input = true;
- }
- Port_Idx nbr_outputs = get_nbr_outputs(m);
- for (Port_Idx idx = 0; idx < nbr_outputs; idx++) {
- RTLIL::Wire *wire = module->addWire(
- to_str(get_output_name(m, idx)),
- get_output_width(m, idx));
- wire->port_output = true;
- }
- module->fixup_ports();
+ Port_Idx nbr_inputs = get_nbr_inputs(m);
+ for (Port_Idx idx = 0; idx < nbr_inputs; idx++) {
+ RTLIL::Wire *wire = module->addWire(
+ to_str(get_input_name(m, idx)),
+ get_input_width(m, idx));
+ wire->port_input = true;
+ }
+ Port_Idx nbr_outputs = get_nbr_outputs(m);
+ for (Port_Idx idx = 0; idx < nbr_outputs; idx++) {
+ RTLIL::Wire *wire = module->addWire(
+ to_str(get_output_name(m, idx)),
+ get_output_width(m, idx));
+ wire->port_output = true;
+ }
+ module->fixup_ports();
return;
- }
+ }
// Create input ports.
// They correspond to ouputs of the self instance.
@@ -368,6 +477,13 @@ static void import_module(RTLIL::Design *design, GhdlSynth::Module m)
}
}
break;
+ case Id_Memory:
+ import_memory(module, net_map, inst);
+ break;
+ case Id_Mem_Rd:
+ case Id_Mem_Wr_Sync:
+ // Handle by import_memory.
+ break;
case Id_Signal:
case Id_Isignal:
case Id_Output:
@@ -568,6 +684,24 @@ static void import_module(RTLIL::Design *design, GhdlSynth::Module m)
case Id_Cover:
module->addCover(to_str(iname), IN(0), State::S1);
break;
+ case Id_Memory:
+ break;
+ case Id_Mem_Rd:
+ {
+ RTLIL::Cell *cell = reinterpret_cast<RTLIL::Cell*>(get_wire(net_map, get_output(inst, 0)));
+ cell->setPort("\\ADDR", IN(1));
+ }
+ break;
+ case Id_Mem_Wr_Sync:
+ {
+ RTLIL::Cell *cell = reinterpret_cast<RTLIL::Cell*>(get_wire(net_map, get_output(inst, 0)));
+ SigSpec data = IN(4);
+ cell->setPort("\\ADDR", IN(1));
+ cell->setPort("\\CLK", IN(2));
+ cell->setPort("\\EN", SigSpec(SigBit(IN(3)), data.size()));
+ cell->setPort("\\DATA", data);
+ }
+ break;
case Id_Const_UB32:
case Id_Const_SB32:
case Id_Const_UL32: