mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 03:32:29 +00:00 
			
		
		
		
	Merge pull request #4981 from jix/faster-liberty-lexing
Improve lexer performance for read_liberty
This commit is contained in:
		
						commit
						26a4b9b0c6
					
				
					 3 changed files with 129 additions and 21 deletions
				
			
		|  | @ -128,6 +128,12 @@ | |||
| #  error "C++17 or later compatible compiler is required" | ||||
| #endif | ||||
| 
 | ||||
| #if defined(__has_cpp_attribute) && __has_cpp_attribute(gnu::cold) | ||||
| #  define YS_COLD [[gnu::cold]] | ||||
| #else | ||||
| #  define YS_COLD | ||||
| #endif | ||||
| 
 | ||||
| #include "kernel/io.h" | ||||
| 
 | ||||
| YOSYS_NAMESPACE_BEGIN | ||||
|  |  | |||
|  | @ -32,6 +32,61 @@ | |||
| 
 | ||||
| using namespace Yosys; | ||||
| 
 | ||||
| bool LibertyInputStream::extend_buffer_once() | ||||
| { | ||||
| 	if (eof) | ||||
| 		return false; | ||||
| 
 | ||||
| 	// To support unget we leave the last already read character in the buffer
 | ||||
| 	if (buf_pos > 1) { | ||||
| 		size_t move_pos = buf_pos - 1; | ||||
| 		memmove(buffer.data(), buffer.data() + move_pos, buf_end - move_pos); | ||||
| 		buf_pos -= move_pos; | ||||
| 		buf_end -= move_pos; | ||||
| 	} | ||||
| 
 | ||||
| 	const size_t chunk_size = 4096; | ||||
| 	if (buffer.size() < buf_end + chunk_size) { | ||||
| 		buffer.resize(buf_end + chunk_size); | ||||
| 	} | ||||
| 
 | ||||
| 	size_t read_size = f.rdbuf()->sgetn(buffer.data() + buf_end, chunk_size); | ||||
| 	buf_end += read_size; | ||||
| 	if (read_size < chunk_size) | ||||
| 		eof = true; | ||||
| 	return read_size != 0; | ||||
| } | ||||
| 
 | ||||
| bool LibertyInputStream::extend_buffer_at_least(size_t size) { | ||||
| 	while (buffered_size() < size) { | ||||
| 		if (!extend_buffer_once()) | ||||
| 			return false; | ||||
| 	} | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| int LibertyInputStream::get_cold() | ||||
| { | ||||
| 	if (buf_pos == buf_end) { | ||||
| 		if (!extend_buffer_at_least()) | ||||
| 			return EOF; | ||||
| 	} | ||||
| 
 | ||||
| 	int c = buffer[buf_pos]; | ||||
| 	buf_pos += 1; | ||||
| 	return c; | ||||
| } | ||||
| 
 | ||||
| int LibertyInputStream::peek_cold(size_t offset) | ||||
| { | ||||
| 	if (buf_pos + offset >= buf_end) { | ||||
| 		if (!extend_buffer_at_least(offset + 1)) | ||||
| 			return EOF; | ||||
| 	} | ||||
| 
 | ||||
| 	return buffer[buf_pos + offset]; | ||||
| } | ||||
| 
 | ||||
| LibertyAst::~LibertyAst() | ||||
| { | ||||
| 	for (auto child : children) | ||||
|  | @ -237,15 +292,19 @@ int LibertyParser::lexer(std::string &str) | |||
| 
 | ||||
| 	// search for identifiers, numbers, plus or minus.
 | ||||
| 	if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9') || c == '_' || c == '-' || c == '+' || c == '.') { | ||||
| 		str = static_cast<char>(c); | ||||
| 		while (1) { | ||||
| 			c = f.get(); | ||||
| 		f.unget(); | ||||
| 		size_t i = 1; | ||||
| 		while (true) { | ||||
| 			c = f.peek(i); | ||||
| 			if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9') || c == '_' || c == '-' || c == '+' || c == '.') | ||||
| 				str += c; | ||||
| 				i += 1; | ||||
| 			else | ||||
| 				break; | ||||
| 		} | ||||
| 		f.unget(); | ||||
| 		str.clear(); | ||||
| 		str.append(f.buffered_data(), f.buffered_data() + i); | ||||
| 		f.consume(i); | ||||
| 
 | ||||
| 		if (str == "+" || str == "-") { | ||||
| 			/* Single operator is not an identifier */ | ||||
| 			// fprintf(stderr, "LEX: char >>%s<<\n", str.c_str());
 | ||||
|  | @ -260,23 +319,24 @@ int LibertyParser::lexer(std::string &str) | |||
| 	// if it wasn't an identifer, number of array range,
 | ||||
| 	// maybe it's a string?
 | ||||
| 	if (c == '"') { | ||||
| 		str = ""; | ||||
| #ifdef FILTERLIB | ||||
| 		str += c; | ||||
| #endif | ||||
| 		while (1) { | ||||
| 			c = f.get(); | ||||
| 			if (c == '\n') | ||||
| 				line++; | ||||
| 			if (c == '"') { | ||||
| #ifdef FILTERLIB | ||||
| 				str += c; | ||||
| #endif | ||||
| 		size_t i = 0; | ||||
| 		while (true) { | ||||
| 			c = f.peek(i); | ||||
| 			line += (c == '\n'); | ||||
| 			if (c != '"') | ||||
| 				i += 1; | ||||
| 			else | ||||
| 				break; | ||||
| 			} | ||||
| 			str += c; | ||||
| 		} | ||||
| 		// fprintf(stderr, "LEX: string >>%s<<\n", str.c_str());
 | ||||
| 		str.clear(); | ||||
| #ifdef FILTERLIB | ||||
| 		f.unget(); | ||||
| 		str.append(f.buffered_data(), f.buffered_data() + i + 2); | ||||
| 		f.consume(i + 2); | ||||
| #else | ||||
| 		str.append(f.buffered_data(), f.buffered_data() + i); | ||||
| 		f.consume(i + 1); | ||||
| #endif | ||||
| 		return 'v'; | ||||
| 	} | ||||
| 
 | ||||
|  |  | |||
|  | @ -90,12 +90,54 @@ namespace Yosys | |||
| 		bool eval(dict<std::string, bool>& values); | ||||
| 	}; | ||||
| 
 | ||||
| 	class LibertyInputStream { | ||||
| 		std::istream &f; | ||||
| 		std::vector<char> buffer; | ||||
| 		size_t buf_pos = 0; | ||||
| 		size_t buf_end = 0; | ||||
| 		bool eof = false; | ||||
| 
 | ||||
| 		bool extend_buffer_once(); | ||||
| 		bool extend_buffer_at_least(size_t size = 1); | ||||
| 
 | ||||
| 		YS_COLD int get_cold(); | ||||
| 		YS_COLD int peek_cold(size_t offset); | ||||
| 
 | ||||
| 	public: | ||||
| 		LibertyInputStream(std::istream &f) : f(f) {} | ||||
| 
 | ||||
| 		size_t buffered_size() { return buf_end - buf_pos; } | ||||
| 		const char *buffered_data() { return buffer.data() + buf_pos; } | ||||
| 
 | ||||
| 		int get() { | ||||
| 			if (buf_pos == buf_end) | ||||
| 				return get_cold(); | ||||
| 			int c = buffer[buf_pos]; | ||||
| 			buf_pos += 1; | ||||
| 			return c; | ||||
| 		} | ||||
| 
 | ||||
| 		int peek(size_t offset = 0) { | ||||
| 			if (buf_pos + offset >= buf_end) | ||||
| 				return peek_cold(offset); | ||||
| 			return buffer[buf_pos + offset]; | ||||
| 		} | ||||
| 
 | ||||
| 		void consume(size_t n = 1) { | ||||
| 			buf_pos += n; | ||||
| 		} | ||||
| 
 | ||||
| 		void unget() { | ||||
| 			buf_pos -= 1; | ||||
| 		} | ||||
| 	}; | ||||
| 
 | ||||
| 	class LibertyMergedCells; | ||||
| 	class LibertyParser | ||||
| 	{ | ||||
| 		friend class LibertyMergedCells; | ||||
| 	private: | ||||
| 		std::istream &f; | ||||
| 		LibertyInputStream f; | ||||
| 		int line; | ||||
| 
 | ||||
| 		/* lexer return values:
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue