From 01001a9cb752dad8ea0a1f451fbf5f4499ccd0b7 Mon Sep 17 00:00:00 2001 From: Tristan Gingold Date: Sun, 3 Nov 2019 17:38:57 +0100 Subject: rewrite import_memory, directly generate $mem --- src/ghdl.cc | 227 ++++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 130 insertions(+), 97 deletions(-) (limited to 'src/ghdl.cc') diff --git a/src/ghdl.cc b/src/ghdl.cc index 6a17c35..94a185c 100644 --- a/src/ghdl.cc +++ b/src/ghdl.cc @@ -226,6 +226,7 @@ static RTLIL::SigSpec get_src(std::vector &net_map, Net n) log_cmd_error("wire not found for %s\n", to_str(get_module_name(get_module(inst))).c_str()); break; } +#undef IN } static bool is_set(std::vector &net_map, Net n) @@ -246,13 +247,12 @@ static void set_src(std::vector &net_map, Net n, Wire *wire) net_map[n.id] = wire; } +// INST is an Id_Memory or an Id_Memory_Init +// All the inputs have been connected, all the outputs have been pushed. static void import_memory(RTLIL::Module *module, std::vector &net_map, Instance inst) { - Input port_inp; - Instance port; Net mem_o = get_output(inst, 0); - Net port_o; - unsigned prio = 0; + Input first_port = get_first_sink (mem_o); std::string mem_str = to_str(get_instance_name(inst)); // Memories appear only once. @@ -260,91 +260,126 @@ static void import_memory(RTLIL::Module *module, std::vector &net // 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); + memory->name = "$mem$" + mem_str; // 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)) { + // Count number of read and write ports. + // Extract width, size, abits. + unsigned nbr_rd = 0; + unsigned nbr_wr = 0; + unsigned width = 0; + unsigned abits = 0; + for (Input port = first_port; port.id != 0;) { + Instance port_inst = get_input_parent(port); + Net addr; + Net dat; + switch(get_id(port_inst)) { 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(cell)); - } - break; + dat = get_output(port_inst, 1); + addr = get_input_net(port_inst, 1); + nbr_rd++; + 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(cell)); - } - break; + dat = get_input_net(port_inst, 4); + addr = get_input_net(port_inst, 1); + nbr_wr++; + break; default: log_assert(0); } - if (memory->width == 0) { - memory->width = port_width; - memory->size = get_width(mem_o) / memory->width; + if (width == 0) { + width = get_width(dat); + abits = get_width(addr); } else { - log_assert(port_width == (unsigned)memory->width); + // All the ports must have the same width and abits. + log_assert(width == get_width(dat)); + log_assert(abits == get_width(addr)); } + port = get_first_sink(get_output(port_inst, 0)); + } - port_inp = get_first_sink(port_o); + unsigned size = get_width(mem_o) / width; + memory->width = width; + memory->size = size; + memory->start_offset = 0; + + // Create the memory. + Cell *mem = module->addCell(mem_str, "$mem"); + mem->parameters["\\MEMID"] = Const(mem_str); + mem->parameters["\\WIDTH"] = Const(width); + mem->parameters["\\OFFSET"] = Const(0); + mem->parameters["\\SIZE"] = Const(size); + mem->parameters["\\ABITS"] = Const(abits); + + Const init_data; + switch (get_id(inst)) { + case Id_Memory: + init_data = Const(State::Sx, size * width); + break; + case Id_Memory_Init: + init_data = get_src(net_map, get_input_net(inst, 0)).as_const(); + break; + default: + log_assert(0); + } + mem->parameters["\\INIT"] = init_data; + mem->parameters["\\WR_PORTS"] = Const(nbr_wr); + mem->parameters["\\RD_PORTS"] = Const(nbr_rd); + + // Connect. + SigSpec rd_clk; + SigSpec rd_addr; + SigSpec rd_data; + SigSpec rd_en; + std::vector rd_clk_en; + SigSpec wr_clk; + SigSpec wr_addr; + SigSpec wr_data; + SigSpec wr_en; + for (Input port = first_port; port.id != 0; ) { + Instance port_inst = get_input_parent(port); +#define IN(N) get_src(net_map, get_input_net(port_inst, (N))) +#define OUT(N) get_src(net_map, get_output(port_inst, (N))) + switch(get_id(port_inst)) { + case Id_Mem_Rd: + rd_clk_en.push_back(RTLIL::State::S0); + rd_clk.append(RTLIL::State::Sx); + rd_addr.append(IN(1)); + rd_data.append(OUT(1)); + rd_en.append(Const(1, 1)); + break; + case Id_Mem_Wr_Sync: + wr_clk.append(IN(2)); + wr_addr.append(IN(1)); + wr_data.append(IN(4)); + wr_en.append(SigSpec(SigBit(IN(3)), width)); + break; + default: + log_assert(0); + } + port = get_first_sink(get_output(port_inst, 0)); } +#undef IN +#undef OUT + mem->parameters["\\RD_CLK_ENABLE"] = nbr_rd ? Const(rd_clk_en) : Const(0, 1); + mem->parameters["\\RD_CLK_POLARITY"] = Const(RTLIL::State::S1, nbr_rd ? nbr_rd : 1); + mem->parameters["\\RD_TRANSPARENT"] = Const(RTLIL::State::S0, nbr_rd ? nbr_rd : 1); + + mem->setPort("\\RD_CLK", rd_clk); + mem->setPort("\\RD_ADDR", rd_addr); + mem->setPort("\\RD_DATA", rd_data); + mem->setPort("\\RD_EN", rd_en); + + mem->parameters["\\WR_CLK_ENABLE"] = Const(RTLIL::State::S1, nbr_wr ? nbr_wr : 1); + mem->parameters["\\WR_CLK_POLARITY"] = Const(RTLIL::State::S1, nbr_wr ? nbr_wr : 1); + + mem->setPort("\\WR_CLK", wr_clk); + mem->setPort("\\WR_ADDR", wr_addr); + mem->setPort("\\WR_DATA", wr_data); + mem->setPort("\\WR_EN", wr_en); } static void add_formal_input(RTLIL::Module *module, std::vector &net_map, Instance inst, const char *cellname) @@ -376,6 +411,9 @@ static void import_module(RTLIL::Design *design, GhdlSynth::Module m) return; } + // List of all memories. + std::vector memories; + Instance self_inst = get_self_instance (m); if (!is_valid(self_inst)) { // blackbox module->set_bool_attribute("\\blackbox"); @@ -473,14 +511,11 @@ static void import_module(RTLIL::Design *design, GhdlSynth::Module m) case Id_Asr: case Id_Smul: case Id_Umul: - case Id_Assert: // No output - case Id_Assume: // No output - case Id_Cover: // No output - case Id_Assert_Cover: // No output case Id_Allconst: case Id_Allseq: case Id_Anyconst: case Id_Anyseq: + case Id_Mem_Rd: case Id_User_None: for (Port_Idx idx = 0; idx < get_nbr_outputs(im); idx++) { Net o = get_output(inst, idx); @@ -492,12 +527,16 @@ static void import_module(RTLIL::Design *design, GhdlSynth::Module m) } } break; - case Id_Memory: - import_memory(module, net_map, inst); + case Id_Assert: + case Id_Assume: + case Id_Cover: + case Id_Assert_Cover: + // No output break; - case Id_Mem_Rd: + case Id_Memory: + case Id_Memory_Init: case Id_Mem_Wr_Sync: - // Handle by import_memory. + // Handled by import_memory. break; case Id_Signal: case Id_Isignal: @@ -713,23 +752,13 @@ static void import_module(RTLIL::Design *design, GhdlSynth::Module m) add_formal_input(module, net_map, inst, "$anyseq"); break; case Id_Memory: + case Id_Memory_Init: + // Will be handled later. + memories.push_back(inst); break; case Id_Mem_Rd: - { - RTLIL::Cell *cell = reinterpret_cast(get_wire(net_map, get_output(inst, 0))); - cell->setPort("\\ADDR", IN(1)); - } - break; case Id_Mem_Wr_Sync: - { - RTLIL::Cell *cell = reinterpret_cast(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; + break; case Id_Const_UB32: case Id_Const_SB32: case Id_Const_UL32: @@ -758,6 +787,10 @@ static void import_module(RTLIL::Design *design, GhdlSynth::Module m) } } + for (auto i : memories) { + import_memory(module, net_map, i); + } + // Connect output drivers to output for (Port_Idx idx = 0; idx < nbr_outputs; idx++) { Net output_out = get_input_net(self_inst, idx); -- cgit v1.2.3