frontends/ast/simplify.cc
// replace a readmem[bh] TCALL ast node with a block of memory assignments
replace a readmem[bh] TCALL ast node with a block of memory assignments
replace a readmem [ bh ] TCALL ast node with a block of memory assignments
AstNode *AstNode::readmem(bool is_readmemh, std::string mem_filename, AstNode *memory, int start_addr, int finish_addr, bool unconditional_init)
{
	int mem_width, mem_size, addr_bits;
	memory->meminfo(mem_width, mem_size, addr_bits);
	AstNode *block = new AstNode(AST_BLOCK);
	AstNode *meminit = nullptr;
	int next_meminit_cursor=0;
	vector<State> meminit_bits;
	int meminit_size=0;
	std::ifstream f;
	f.open(mem_filename.c_str());
	if (f.fail()) {
#ifdef _WIN32
		char slash = '\\';
#else
		char slash = '/';
#endif
		std::string path = filename.substr(0, filename.find_last_of(slash)+1);
		f.open(path + mem_filename.c_str());
		yosys_input_files.insert(path + mem_filename);
	} else {
		yosys_input_files.insert(mem_filename);
	}
	if (f.fail() || GetSize(mem_filename) == 0)
		log_file_error(filename, location.first_line, "Can not open file `%s` for %s.\n", mem_filename.c_str(), str.c_str());
	log_assert(GetSize(memory->children) == 2 && memory->children[1]->type == AST_RANGE && memory->children[1]->range_valid);
	int range_left =  memory->children[1]->range_left, range_right =  memory->children[1]->range_right;
	int range_min = min(range_left, range_right), range_max = max(range_left, range_right);
	if (start_addr < 0)
		start_addr = range_min;
	if (finish_addr < 0)
		finish_addr = range_max + 1;
	bool in_comment = false;
	int increment = start_addr <= finish_addr ? +1 : -1;
	int cursor = start_addr;
	while (!f.eof())
	{
		std::string line, token;
		std::getline(f, line);
		for (int i = 0; i < GetSize(line); i++) {
			if (in_comment && line.compare(i, 2, "*/") == 0) {
				line[i] = ' ';
				line[i+1] = ' ';
				in_comment = false;
				continue;
			}
			if (!in_comment && line.compare(i, 2, "/*") == 0)
				in_comment = true;
			if (in_comment)
				line[i] = ' ';
		}
		while (1)
		{
			token = next_token(line, " \t\r\n");
			if (token.empty() || token.compare(0, 2, "//") == 0)
				break;
			if (token[0] == '@') {
				token = token.substr(1);
				const char *nptr = token.c_str();
				char *endptr;
				cursor = strtol(nptr, &endptr, 16);
				if (!*nptr || *endptr)
					log_file_error(filename, location.first_line, "Can not parse address `%s` for %s.\n", nptr, str.c_str());
				continue;
			}
			AstNode *value = VERILOG_FRONTEND::const2ast(stringf("%d'%c", mem_width, is_readmemh ? 'h' : 'b') + token);
			if (unconditional_init)
			{
				if (meminit == nullptr || cursor != next_meminit_cursor)
				{
					if (meminit != nullptr) {
						meminit->children[1] = AstNode::mkconst_bits(meminit_bits, false);
						meminit->children[2] = AstNode::mkconst_int(meminit_size, false);
					}
					meminit = new AstNode(AST_MEMINIT);
					meminit->children.push_back(AstNode::mkconst_int(cursor, false));
					meminit->children.push_back(nullptr);
					meminit->children.push_back(nullptr);
					meminit->str = memory->str;
					meminit->id2ast = memory;
					meminit_bits.clear();
					meminit_size = 0;
					current_ast_mod->children.push_back(meminit);
					next_meminit_cursor = cursor;
				}
				meminit_size++;
				next_meminit_cursor++;
				meminit_bits.insert(meminit_bits.end(), value->bits.begin(), value->bits.end());
				delete value;
			}
			else
			{
				block->children.push_back(new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER, new AstNode(AST_RANGE, AstNode::mkconst_int(cursor, false))), value));
				block->children.back()->children[0]->str = memory->str;
				block->children.back()->children[0]->id2ast = memory;
				block->children.back()->children[0]->was_checked = true;
			}
			cursor += increment;
			if ((cursor == finish_addr+increment) || (increment > 0 && cursor > range_max) || (increment < 0 && cursor < range_min))
				break;
		}
		if ((cursor == finish_addr+increment) || (increment > 0 && cursor > range_max) || (increment < 0 && cursor < range_min))
			break;
	}
	if (meminit != nullptr) {
		meminit->children[1] = AstNode::mkconst_bits(meminit_bits, false);
		meminit->children[2] = AstNode::mkconst_int(meminit_size, false);
	}
	return block;
}
AstNode * AstNode :: readmem ( bool is_readmemh , std :: string mem_filename , AstNode * memory , int start_addr , int finish_addr , bool unconditional_init ) { int mem_width , mem_size , addr_bits ; memory -> meminfo ( mem_width , mem_size , addr_bits ) ; AstNode * block = new AstNode ( AST_BLOCK ) ; AstNode * meminit = nullptr ; int next_meminit_cursor = 0 ; vector < State > meminit_bits ; int meminit_size = 0 ; std :: ifstream f ; f . open ( mem_filename . c_str ( ) ) ; if ( f . fail ( ) ) { #ifdef _WIN32 char slash = ' \\ ' ; #else char slash = ' ' ; #endif std :: string path = filename . substr ( 0 , filename . find_last_of ( slash ) + 1 ) ; f . open ( path + mem_filename . c_str ( ) ) ; yosys_input_files . insert ( path + mem_filename ) ; } else { yosys_input_files . insert ( mem_filename ) ; } if ( f . fail ( ) || GetSize ( mem_filename ) == 0 ) log_file_error ( filename , location . first_line , " \n " , mem_filename . c_str ( ) , str . c_str ( ) ) ; log_assert ( GetSize ( memory -> children ) == 2 && memory -> children [ 1 ] -> type == AST_RANGE && memory -> children [ 1 ] -> range_valid ) ; int range_left = memory -> children [ 1 ] -> range_left , range_right = memory -> children [ 1 ] -> range_right ; int range_min = min ( range_left , range_right ) , range_max = max ( range_left , range_right ) ; if ( start_addr < 0 ) start_addr = range_min ; if ( finish_addr < 0 ) finish_addr = range_max + 1 ; bool in_comment = false ; int increment = start_addr <= finish_addr ? +1 : -1 ; int cursor = start_addr ; while ( ! f . eof ( ) ) { std :: string line , token ; std :: getline ( f , line ) ; for ( int i = 0 ; i < GetSize ( line ) ; i ++ ) { if ( in_comment && line . compare ( i , 2 , " " ) == 0 ) { line [ i ] = ' ' ; line [ i + 1 ] = ' ' ; in_comment = false ; continue ; } if ( ! in_comment && line . compare ( i , 2 , " " ) == 0 ) in_comment = true ; if ( in_comment ) line [ i ] = ' ' ; } while ( 1 ) { token = next_token ( line , " \t \r \n " ) ; if ( token . empty ( ) || token . compare ( 0 , 2 , " " ) == 0 ) break ; if ( token [ 0 ] == ' ' ) { token = token . substr ( 1 ) ; const char * nptr = token . c_str ( ) ; char * endptr ; cursor = strtol ( nptr , & endptr , 16 ) ; if ( ! * nptr || * endptr ) log_file_error ( filename , location . first_line , " \n " , nptr , str . c_str ( ) ) ; continue ; } AstNode * value = VERILOG_FRONTEND :: const2ast ( stringf ( " " , mem_width , is_readmemh ? ' ' : ' ' ) + token ) ; if ( unconditional_init ) { if ( meminit == nullptr || cursor != next_meminit_cursor ) { if ( meminit != nullptr ) { meminit -> children [ 1 ] = AstNode :: mkconst_bits ( meminit_bits , false ) ; meminit -> children [ 2 ] = AstNode :: mkconst_int ( meminit_size , false ) ; } meminit = new AstNode ( AST_MEMINIT ) ; meminit -> children . push_back ( AstNode :: mkconst_int ( cursor , false ) ) ; meminit -> children . push_back ( nullptr ) ; meminit -> children . push_back ( nullptr ) ; meminit -> str = memory -> str ; meminit -> id2ast = memory ; meminit_bits . clear ( ) ; meminit_size = 0 ; current_ast_mod -> children . push_back ( meminit ) ; next_meminit_cursor = cursor ; } meminit_size ++ ; next_meminit_cursor ++ ; meminit_bits . insert ( meminit_bits . end ( ) , value -> bits . begin ( ) , value -> bits . end ( ) ) ; delete value ; } else { block -> children . push_back ( new AstNode ( AST_ASSIGN_EQ , new AstNode ( AST_IDENTIFIER , new AstNode ( AST_RANGE , AstNode :: mkconst_int ( cursor , false ) ) ) , value ) ) ; block -> children . back ( ) -> children [ 0 ] -> str = memory -> str ; block -> children . back ( ) -> children [ 0 ] -> id2ast = memory ; block -> children . back ( ) -> children [ 0 ] -> was_checked = true ; } cursor += increment ; if ( ( cursor == finish_addr + increment ) || ( increment > 0 && cursor > range_max ) || ( increment < 0 && cursor < range_min ) ) break ; } if ( ( cursor == finish_addr + increment ) || ( increment > 0 && cursor > range_max ) || ( increment < 0 && cursor < range_min ) ) break ; } if ( meminit != nullptr ) { meminit -> children [ 1 ] = AstNode :: mkconst_bits ( meminit_bits , false ) ; meminit -> children [ 2 ] = AstNode :: mkconst_int ( meminit_size , false ) ; } return block ; }
replace a readmem[bh] TCALL ast node with a block of memory assignments
replace a readmem [ bh ] TCALL ast node with a block of memory assignments