diff options
| author | Tristan Gingold <tgingold@free.fr> | 2019-10-19 10:13:04 +0200 | 
|---|---|---|
| committer | Tristan Gingold <tgingold@free.fr> | 2019-10-19 10:13:04 +0200 | 
| commit | 2141001bc795cd4fd12c9bb3a0f5d689c7840ef5 (patch) | |
| tree | 1b3781c0d23d10c1ff7205c0331e2a65c808fc46 /src | |
| parent | 0b29a7cb792bd07b112671a264defcb1085ba402 (diff) | |
| download | ghdl-yosys-plugin-2141001bc795cd4fd12c9bb3a0f5d689c7840ef5.tar.gz ghdl-yosys-plugin-2141001bc795cd4fd12c9bb3a0f5d689c7840ef5.tar.bz2 ghdl-yosys-plugin-2141001bc795cd4fd12c9bb3a0f5d689c7840ef5.zip  | |
Initial support of memories.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ghdl.cc | 170 | 
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:  | 
