SVD文件转换工具

SVD文件转换工具

用途

转换现有svd文件到 mculib4d 的芯片声明工具

代码查阅

代码

module svd;

import std.stdio;

import std.file;

import std.xml;
import std.string;
import std.regex;

struct tys
{
	union{
		uint		i1;
		ushort[2]	s1;
		ubyte[4]	b1;
	}
}

int main()
{
	string svdfile = "STM32F401.svd";

	if(!isFile(svdfile)){
		return 0;
	}
	
    Etsvd(svdfile);
    return 0;
}

struct mcuinfo
{
    string name;
    string mversion;
    string description;
    string addressUnitBits;
    string width;
    string size;
    string resetValue;
    string resetMask;

    cpuinfo   cpu;
}

struct cpuinfo
{
    string name;
    string revision;
    string endian;
    string mpuPresent;
    string fpuPresent;
    string nvicPrioBits;
    string vendorSystickConfig;
}

struct peripheral
{
    string name;
    string desc;
    string group;
    string    address;
    addressBlock ablock;
    interrupt[] inp;
    register[]  regs;

    string ttext;
    string derivedFrom;
}


struct addressBlock
{
    string offs;
    string ssize;
    string usage;
}

struct interrupt
{
    string name;
    string description;
    string val;
}

struct register
{
    string name;
    string display;
    string description;
    string addressOffset;
    string msize;
    string access;
    string resetValue;
    field[] fields;
}

struct field
{
    string name;
    string description;
    string bitOffset;
    string bitWidth;
    string access;

}



void Etsvd(string fname)
{
    string s = cast(string) std.file.read(fname);
    //
    try{
        //check(s);
	}catch (CheckException e)
	{
        writefln(e.msg);

	}

    peripheral[] pres;
    mcuinfo info;
    
	DocumentParser svdxml = new DocumentParser(s);
    
    svdxml.onEndTag["name"]       = (in Element e) { info.name      = e.text(); };
	svdxml.onEndTag["version"]       = (in Element e) { info.mversion      = e.text(); };
	svdxml.onEndTag["description"]       = (in Element e) { info.description      = e.text(); };
	svdxml.onStartTag["cpu"] = (ElementParser cp){
		cpuinfo mcup;
		cp.onEndTag["name"]  = (in Element e) { mcup.name      = e.text(); };
		cp.onEndTag["revision"]  = (in Element e) { mcup.revision      = e.text(); };
		cp.onEndTag["endian"]  = (in Element e) { mcup.endian      = e.text(); };
		cp.onEndTag["mpuPresent"]  = (in Element e) { mcup.mpuPresent      = e.text(); };
		cp.onEndTag["fpuPresent"]  = (in Element e) { mcup.fpuPresent      = e.text(); };
		cp.onEndTag["nvicPrioBits"]  = (in Element e) { mcup.nvicPrioBits      = e.text(); };
		cp.onEndTag["vendorSystickConfig"]  = (in Element e) { mcup.vendorSystickConfig      = e.text(); };
		cp.parse();
		info.cpu = mcup;
	};
	svdxml.onEndTag["addressUnitBits"]       = (in Element e) { info.addressUnitBits      = e.text(); };
	svdxml.onEndTag["width"]       = (in Element e) { info.width      = e.text(); };
	svdxml.onEndTag["size"]       = (in Element e) { info.size      = e.text(); };
	svdxml.onEndTag["resetValue"]       = (in Element e) { 
		info.resetValue      = e.text(); 
	};
	svdxml.onEndTag["resetMask"]       = (in Element e) { info.resetMask      = e.text(); };

	svdxml.onStartTag["peripheral"] = (ElementParser xml)
	{
		peripheral pb;

		auto df = ("derivedFrom" in xml.tag.attr);
		if(df){
			pb.derivedFrom = *df;
		}

		xml.onEndTag["name"]       = (in Element e) { pb.name      = e.text(); };
		xml.onEndTag["description"]  = (in Element e) { pb.desc = e.text(); };
		xml.onEndTag["groupName"]        = (in Element e) { pb.group       = e.text(); };
		xml.onEndTag["baseAddress"]        = (in Element e) { pb.address       = e.text(); };

		//xml.onEndTag["addressBlock"]        = (in Element e) { 	pb.ttext       = e.text();	};
		xml.onStartTag["addressBlock"] = (ElementParser ap){
			addressBlock ab;
			ap.onEndTag["offset"] = (in Element e){ab.offs = e.text();};
			ap.onEndTag["size"] = (in Element e){ab.ssize = e.text();};
			ap.onEndTag["usage"] = (in Element e){ab.usage = e.text();};

			ap.parse();
			pb.ablock = ab;
		};
		xml.onStartTag["interrupt"] = (ElementParser p){
			interrupt ip;
			p.onEndTag["name"] = (in Element e){ip.name = e.text();};
			p.onEndTag["description"] = (in Element e){ip.description = e.text();};
			p.onEndTag["value"] = (in Element e){ip.val = e.text();};

			p.parse();
			pb.inp ~= ip;
		};

		xml.onStartTag["register"] = (ElementParser ep){
			register reg;
			ep.onEndTag["name"] = (in Element e){reg.name = e.text();};
			ep.onEndTag["displayName"] = (in Element e){reg.display = e.text();};
			ep.onEndTag["description"] = (in Element e){reg.description = e.text();};
			ep.onEndTag["addressOffset"] = (in Element e){reg.addressOffset = e.text();};
			ep.onEndTag["size"] = (in Element e){reg.msize = e.text();};
			ep.onEndTag["access"] = (in Element e){reg.access = e.text();};
			ep.onEndTag["resetValue"] = (in Element e){reg.resetValue = e.text();};

			ep.onStartTag["field"] = (ElementParser fp){
				field fid;
				fp.onEndTag["name"] = (in Element e){fid.name = e.text();};
				fp.onEndTag["description"] = (in Element e){fid.description = e.text();};
				fp.onEndTag["bitOffset"] = (in Element e){fid.bitOffset = e.text();};
				fp.onEndTag["bitWidth"] = (in Element e){fid.bitWidth = e.text();};
				fp.onEndTag["access"] = (in Element e){fid.access = e.text();};

				fp.parse();
				reg.fields ~= fid;
			};

			ep.parse();
			pb.regs ~= reg;
		};

		xml.parse();
		pres ~= pb;
	};

    svdxml.parse();
    //---
    peripheral scan4name(string n)
	{
        foreach(v;pres)
		{
            if(v.name == n) return v;
		}
		writefln("no found [%s]",n);
        return peripheral.init;
	}

    //--
	/// 模板统计

    foreach(ref v;pres)
	{
        if(v.derivedFrom.length > 0){
            auto vf = scan4name(v.derivedFrom);
            vf.name = v.name;
            vf.address = v.address;
			vf.derivedFrom = v.derivedFrom;
			vf.inp = v.inp;
            v = vf;
		}
	}

    //--
    
	//-- 模板

    //-- 组
    string code;
    
    
    //-- 组函数
	
    //-- 常量
	
    if(info.description){
        code ~= maker_description(info.description,0,90);
	}
    code ~= "struct Conf {\n";

	code ~= "\tenum string SVDName                  = `"~info.name~"`;\n";
	code ~= "\tenum string SVDVersion               = `"~info.mversion~"`;\n";
	code ~= "\tenum size_t SVDUnitBits              = "~info.addressUnitBits~";\n";
	code ~= "\tenum size_t SVDWidth                 = "~info.width~";\n";
	code ~= "\tenum size_t SVDSize                  = "~info.size~";\n";
	code ~= "\tenum size_t SVDresetValue            = "~info.resetValue~";\n";
	code ~= "\tenum size_t SVDresetMask             = "~info.resetMask~";\n";

	code ~= "\tenum string SVDCpuName               = `"~info.cpu.name~"`;\n";
	code ~= "\tenum string SVDCpuRevision           = `"~info.cpu.revision~"`;\n";
	code ~= "\tenum string SVDCpuEndian             = `"~info.cpu.endian~"`;\n";
	code ~= "\tenum bool SVDCpuMpuPresent           = "~info.cpu.mpuPresent~";\n";
	code ~= "\tenum bool SVDCpuFpuPresent           = "~info.cpu.fpuPresent~";\n";
	code ~= "\tenum size_t SVDCpuNvicPrioBits       = "~info.cpu.nvicPrioBits~";\n";
	code ~= "\tenum bool SVDCpuVendorSystickConfig  = "~info.cpu.vendorSystickConfig~";\n";

    code ~= "}\n";

	code ~= maker_group(pres);

	writeln(code);

}

void maker_group1(peripheral[] src)
{
	import std.algorithm;
	void maker_group_sin(string gname)
	{
	}
	//uint[string] groups;
	string[]	groups;
	uint[string]	tgroup;
	string code;

	bool pmcheck(string n)
	{
		foreach(v;groups)
		{
			if(v == n) return true;
		}
		return false;
	}

	peripheral[]	pmSumGroup(string n)
	{
		peripheral[] r;
		foreach(v;src){
			if(v.group == n) r ~= v;
		}
		return r;
	}

	uint pmCount(string n)
	{

		return pmSumGroup(n).length;
	}

	string pmMakeTname(string v1,string v2)
	{
		string r;
		auto msize = (v1.length <= v2.length) ?v1.length:v2.length;
		for(auto i = 0;i<msize;i++)
		{
			if(v1[i] is v2[i]){
				r ~=v1[i];
			}else{
				break;
			}
		}
		return r;
	}

	uint pmCountTP(peripheral[] g)
	{
		uint[string] count;
		auto tg = g.dup;

		while(tg.length){
			auto cv = tg[0];
			tg = tg[1..$];
			peripheral[] t;
			
			foreach(v;tg){
				
				if(cv.name.indexOf("GPIO") >= 0)
				{
					auto b1 = cv.regs is v.regs;
					auto b2 = v.regs == cv.regs;
					writeln(b1);
					writeln(b2);
					writeln(cv.name);
					writeln(v.name);
				}
				
				if(cv.regs is v.regs){
					count[pmMakeTname(v.name,cv.name)]++;
				}else{
					t ~= v;
				}
				
			}
			tg = t;
		}

		writeln(count);

		return 0;
	}

	peripheral[]	pmSumderivedFrom(string n)
	{
		peripheral[] r;
		foreach(v;src){
			if(v.derivedFrom == n) r ~= v;
		}
		return r;
	}
	//组
    foreach(v;src){
		if(!pmcheck(v.group)) groups ~= v.group;
	}
	// 模板组
	foreach(v;src)
	{
		if(v.derivedFrom.length > 0)
		{
			tgroup[v.derivedFrom]++;
		}
	}
	// 建立模板
	foreach(v,v2;tgroup){
		if(v){
			auto tp = pmSumderivedFrom(v);
			auto tname = "";

			foreach(k,vn;v)
			{
				foreach(tv;tp)
				{
					if(!(tv.name[k] == vn)){
						goto enddd;
					}
				}
				tname ~= vn;
			}
			enddd:
			if(tname.length==0){
				tname = v;
			}

			//writeln();
			code ~= "\n/****************************************************************************************\n";
			code ~= "*\t package template: "~ tname ~ "\n";
			code ~= "*/\n";
		}
		//if(!pmcheck(v.group)) groups ~= v.group;
	}

	/+


	foreach(k;groups)
	{
		//pmCountTP(pmSumGroup(k));
		//writefln("Key[%s],count[%s]",k,pmCount(k));
		code ~= "\n/****************************************************************************************\n";
		code ~= "*\t Group: "~ k ~ "\n";
        code ~= "*/\n";

	}
	+/
	//writeln(code);
	//writeln(maker_description("ccccaaa",8));
	writeln(maker_Peripheral(src[0]));
}
/*
	Group > Temp > Const
*/
string maker_group(peripheral[] src)
{
	peripheral[][string] tgroups;
	string code;
	foreach(v;src)
	{
		if(v.derivedFrom.length > 0)
		{
			tgroups[v.derivedFrom] ~= v;
		}
	}
	// 整理
	foreach(k,v;tgroups)
	{
		foreach(ref dv;src){
			if(dv.name == k){
				dv.derivedFrom = k;
				tgroups[k] ~= dv;
				break;
			}
		}
	}


	/*
	foreach(dv;src)
	{
	if(dv.name == v.derivedFrom ) 
	{
	tgroups[v.derivedFrom] ~= dv;
	break;
	}
	}
	*/
	
	//模板目标
	foreach(dfname,pv;tgroups)
	{
		auto tname="";
		//foreach()
		foreach(i,s;dfname)
		{
			foreach(tv;pv){
				if(!(tv.name[i] == s))
				{
					goto endddd;
				}
			}
			tname ~= s;
		}
		endddd:
		if(tname.length == 0){
			tname = dfname;
		}

		code ~= maker_desc1(0,90);
		//模板声明
		foreach(v;pv)
		{
			code ~= format("/// %s\n",ClearRN(v.desc));
			//code ~= format("alias %s = %sTemplate!(%s);\n",v.name,dfname,v.address);
			code ~= format("final abstract class %s : %sTemplate!(%s) {\n",v.name,dfname,v.address);

			// 中断
			if(v.inp ){
				code ~= maker_tab(4) ~ "///";
				foreach(iv;v.inp)
				{
					code ~= iv.name;
					code ~= ",";
				}
				code ~= "\n";
				code ~= maker_tab(4) ~ "enum interrupts=[";
				foreach(iv;v.inp)
				{
					code ~= iv.val;
					code ~= ",";
				}
				code ~= "];\n";
			}
			

			code ~= "}\n";

		}
		//模板建立
		auto tpv = pv[0];
		tpv.name = dfname;
		code ~= maker_Peripheral(tpv,true);
	}

	foreach(v;src)
	{
		if(v.derivedFrom) continue;
		code ~= maker_Peripheral(v,false);
	}

	return code;
}

string maker_Peripheral(in peripheral src,bool istemplate=false)
{
	string code;

	//code ~= "final abstract class SPI4 : Peripheral!(0x40013400,Conf) \n";
	if(istemplate){
		code ~= maker_description(ClearRN(src.name));
		code ~= format("private abstract class %sTemplate(size_t pBase) : Peripheral!(pBase,Conf) {\n",src.name);
	}else{
		code ~= maker_description(ClearRN(src.desc));
		code ~= format("final abstract class %s : Peripheral!(%s,Conf) {\n",src.name,src.address);
	}
	// 中断
	if(src.inp && !(istemplate)){
		code ~= maker_tab(4) ~ "///";
		foreach(iv;src.inp)
		{
			code ~= iv.name;
			code ~= ",";
		}
		code ~= "\n";
		code ~= maker_tab(4) ~ "enum interrupts=[";
		foreach(iv;src.inp)
		{
			code ~= iv.val;
			code ~= ",";
		}
		code ~= "];\n";
	}
	foreach(rv;src.regs){
		//code ~= maker_description(ClearRN(rv.description),4);
		code ~= maker_tab(4);
		code ~= format("/// %s\n",ClearRN(rv.description));
		code ~= maker_tab(4);
		code ~= format("final abstract class %s : Register!(%s,Access.%s){\n",rv.name,rv.addressOffset,checkAccess(rv.access));
		
		
		//bit
		foreach(fv;rv.fields)
		{
			//code ~= maker_description(ClearRN(fv.description),8);
			code ~= maker_tab(8);
			code ~= format("/// %s\n",ClearRN(fv.description));

			code ~= maker_tab(8);
			code ~= format("alias %s=Bits!(%s,%s,Access.%s);\n",fv.name,fv.bitOffset,fv.bitWidth,checkAccess(fv.access));
		}

		code ~= maker_tab(4);
		code ~= "}\n";
	}
	code ~= "}\n";
	


	return code;
}

enum tabwidth = 0xff;
string maker_tab(in uint start)
{
	string stab;

	for(auto i=(start / tabwidth);i>0;i--) stab ~= "\t";

	for(auto i=(start % tabwidth);i>0;i--) stab ~= " ";

	return stab;
}
string maker_desc1(in uint start,in uint end)
{
	string ret;
	ret ~= maker_tab(start);
	ret ~= "//";
	for(auto i=(end - start - 2);i>0;i--) ret ~= "-";

	ret ~= "\n";

	return ret;
}
string maker_description(string desc,in uint start = 0,in uint end=90)
{
	string ret;
	string stab;
	string ssp;

	stab = maker_tab(start);


	
	ssp ~= stab ~ "/";
	for(auto i=(end - start - 1);i>0;i--) ssp ~= "*";
	ssp ~= "\n";
	

	//
	ret ~= ssp;
	
	ret ~= stab;
	ret ~= "*\t" ~ desc;
	ret ~= "\n"~stab~"*/\n";

	return ret;
}

string ClearRN(string s)
{
	string r;
	foreach(string line; splitter(s, regex("[\r\n]+") )){
		r ~= line.stripLeft(" ");
	}
	return r;
}

string checkAccess(string s)
{  
	switch(s.toLower()){
		case "read-only": return "ro";
		case "read-write": return "rw";
		case "write-only": return "wo";
		default:break;
	}
	if(s.length) writefln("no:%s",s);
	return "rwa";
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值