游戏开发论坛

 找回密码
 立即注册
搜索
查看: 3058|回复: 9

正在编写 并行计算 虚拟机 (付 源码)

[复制链接]

362

主题

3023

帖子

3553

积分

论坛元老

Rank: 8Rank: 8

积分
3553
发表于 2008-3-22 23:32:00 | 显示全部楼层 |阅读模式
//vm.h

#ifndef INST_PROJ_TINSTVM_VM_H
#define INST_PROJ_TINSTVM_VM_H


#include <instDefines.h>
#include <instList.h>

namespace inst
{
namespace vm
{


//因为是虚拟机,所以只有虚拟机内部能直接完成更复杂的工作,运行速度才更快


class CProcessor;

class CMachine;


typedef UInt32        MEM;

typedef MEM                CODE; // 操作码

typedef MEM                MODE; // 寻址模式

typedef MEM                ARG;  // 操作数(立即数或地址或指针)

typedef MEM                ADDR; // 地址

typedef ADDR        ADDR_REGISTER; // 地址寄存器

typedef UInt32        PORTDATA; // 端口数据类型


//@note : 通过安装适配器到“硬件”端口来调用com
//类似地,不必再机器内部支持库函数等,
//可以利用硬件,进行机器间连接,来实现库函数,
//或者,直接调用硬件中连接的库函数


#define IMPL_FUNC(name)                        void CProcessor::func_##name()

#define DECL_FUNC(name)                        void func_##name();

#define DEF_CODE(name)                        &func_##name,

#define ENUM_CODE(name)                        code_##name,


class CMachine;


typedef MEM *                                        MEM_BLOCK;

typedef        ArrayList<MEM_BLOCK>        MEM_BLOCKS_LIST;

#define BLOCK_SIZE                                0x10000 // 0x0000 - 0xffff


class CProcessor
{
        friend class CMachine;
private:

        Bool                                m_bKill; //Kill不是全局同步的,也是非预期的,如果需要,应使用Barrier
        Bool                                m_bBarrier;

        Bool                                m_bCreateProc; //建立的Proc只能他自己Kill。不过可以通知他Kill

        ADDR_REGISTER                IP, SP;
        //SS不需要 - 永远为 (0x4000 + 0x8000) << 16 ,这也是SP的初始值

        //C++机器实现的内存块: 0xFFFF

        MEM_BLOCKS_LIST                *m_lstGlobalBlocks;
        MEM_BLOCKS_LIST                m_lstPrivateBlocks;
        MEM_BLOCKS_LIST                m_lstStackBlocks;


        typedef        void (CProcessor:: *FUNC_PTR)(void);

        static FUNC_PTR func_map[];


        //0x0000 FFFF - 0x7FFF FFFF : shared
        //0x7FFF FFFF - 0xFFFF FFFF : private

        //在内存不足时机器将崩溃,也不必作异常处理,因为
        //即使处理,代码本来的逻辑也无法完成
#define GLOBAL_START_ADDR                        0x00000000
#define PRIVATE_START_ADDR                        0x80000000
#define STACK_START_ADDR                        0xC0000000


#define GLOBAL_BLOCK_INDEX(addr)        (((addr)&0xFFFF0000)>>16)                                // 0000` - 7FFF`
#define PRIVATE_BLOCK_INDEX(addr)        ((((addr)&0xFFFF0000)>>16) - 0x8000)        // 8000` - BFFF`
#define STACK_BLOCK_INDEX(addr)                ((((addr)&0xFFFF0000)>>16) - 0xC000)        // C000` - FFFF`
#define ADDR_IN_BLOCK(addr)                        ((addr)&0x0000ffff)

        __forceinline MEM *TransAddr(ADDR addr) //把虚拟机地址(单位 4 bytes)转换为物理地址
        {
                if(addr<=0x7FFFffff)
                        return ( m_lstGlobalBlocks->Get(GLOBAL_BLOCK_INDEX(addr))
                                                + ADDR_IN_BLOCK(addr) );
                else if(addr<=0xBFFFffff)
                        return ( m_lstPrivateBlocks.Get(PRIVATE_BLOCK_INDEX(addr))
                                                + ADDR_IN_BLOCK(addr) );
                else
                        return ( m_lstStackBlocks.Get(STACK_BLOCK_INDEX(addr))
                                                + ADDR_IN_BLOCK(addr) );
        }


        // mode: 0 - 立即数(直接返回arg), 1 - 直接寻址(地址arg指向src) 2 - 间接一次寻址(地址arg指向的数值指向src)

        __forceinline MEM Read(MODE mode, ARG arg)
        {
                if(mode==0)        return arg;
                if(mode==1)        return *TransAddr(arg);
                if(mode==2)        return *TransAddr(*TransAddr(arg));
                                        return *TransAddr(*TransAddr(*TransAddr(arg)));
        }
       
        __forceinline Float ReadF(MODE mode, ARG arg)
        {
                if(mode==0)        return *(Float *)&arg;
                if(mode==1)        return *(Float *)TransAddr(arg);
                if(mode==2)        return *(Float *)TransAddr(*TransAddr(arg));
                                        return *(Float *)TransAddr(*TransAddr(*TransAddr(arg)));
        }


        // mode: 0 - 立即数(不能做左值!)修正为1处理, 1 - 直接寻址(arg就是dest的地址) 2 - 间接一次寻址(arg指向的数值是dest的地址)

        __forceinline void Write(MODE mode, ARG arg, MEM val)
        {
        //        if(mode==0)FireInt(); 出错,产生中断
                if(mode<2)        { *TransAddr(arg)=val; return; }
                if(mode==2)        { *TransAddr(*TransAddr(arg))=val; return; }
                                          *TransAddr(*TransAddr(*TransAddr(arg)))=val;
        }

        __forceinline void WriteF(MODE mode, ARG arg, Float val)
        {
        //        if(mode==0)FireInt(); 出错,产生中断
                if(mode<2)        { *(Float *)TransAddr(arg)=val; return; }
                if(mode==2)        { *(Float *)TransAddr(*TransAddr(arg))=val; return; }
                                          *(Float *)TransAddr(*TransAddr(*TransAddr(arg)))=val;
        }

        __forceinline void Perform()
        {
                (this ->* func_map[*TransAddr(IP++)] )();
        }


        CProcessor(MEM_BLOCKS_LIST *pglobal,ADDR_REGISTER startIP,MEM *pmem,UInt32 size,UInt32 blocks) //private mem only
        {
                m_bKill = False;
                m_bBarrier = False;

                IP = startIP;
                SP = STACK_START_ADDR;

                m_lstGlobalBlocks=pglobal;

                m_lstStackBlocks.Add(new MEM[BLOCK_SIZE]);

                m_lstPrivateBlocks.Resize(blocks);
                for(UInt32 b=0; b<blocks; b++)
                        m_lstPrivateBlocks.Set(b,new MEM[BLOCK_SIZE]);

                for(UInt32 i=0; i<size; i++)
                {
                        *TransAddr(PRIVATE_START_ADDR+i)=pmem;
                }
        }

        ~CProcessor()
        {
        }


        DECL_FUNC(not)
        DECL_FUNC(and)
        DECL_FUNC(or)
        DECL_FUNC(xor)

        DECL_FUNC(bool)

        DECL_FUNC(eq)
        DECL_FUNC(neq)
        DECL_FUNC(lrg)
        DECL_FUNC(sml)
        DECL_FUNC(leq)
        DECL_FUNC(seq)

        DECL_FUNC(add)
        DECL_FUNC(sub)
        DECL_FUNC(mul)
        DECL_FUNC(div)
        DECL_FUNC(mod)

        DECL_FUNC(eqf)
        DECL_FUNC(neqf)
        DECL_FUNC(lrgf)
        DECL_FUNC(smlf)
        DECL_FUNC(leqf)
        DECL_FUNC(seqf)

        DECL_FUNC(addf)
        DECL_FUNC(subf)
        DECL_FUNC(mulf)
        DECL_FUNC(divf)

        DECL_FUNC(mov)

        DECL_FUNC(push)
        DECL_FUNC(pop)

        DECL_FUNC(fti)
        DECL_FUNC(itf)

        DECL_FUNC(nop)
        DECL_FUNC(jmp)
        DECL_FUNC(jt)
        DECL_FUNC(jf)

        DECL_FUNC(call)
        DECL_FUNC(ret)

        DECL_FUNC(in)
        DECL_FUNC(out)

        //寄存器访问(RO)
        DECL_FUNC(ip)
        DECL_FUNC(sp)

        //机器内存管理
        DECL_FUNC(mmg)        // 通知Machine设置global内存Block数目,并分配每一个Block
        DECL_FUNC(mmp)        // 设置private内存Block数目,并分配每一个Block

        //机器和处理器控制指令
        DECL_FUNC(brr)        // 障碍同步,*非*全局的
//        DECL_FUNC(lck)                //暂停其他处理器 - 以达到内存访问的“互斥”。。。能用barrier模拟?
                                                //win32的mutex只是确保安全,而不确保线程步调一致!
                                                //但是如果用BARRIER,连步调都一致了,更不用说安全数据访问了

                        //不论怎样,基本数据类型的数据是不可能在同一时刻被多线程写入的。
                        //但是,假如说考虑一个同时可写的计算模型。。。就会产生矛盾。。。
                        //但系统就不同了。。。所以计算模型和系统模型是不同的。

                                //还有一种结构体数据安全写入方法是,在private中的临时变量中写好
                                //然后使用*串操作*指令,一次性写入。。。

                                //去掉串操作,否则就不能模拟并行执行了,
                                //还有mode次数也要限制为1111=7
//----------------------------------------------------------------
        //或者把lck改为,锁定sharedmemory的写入,
        //不写入sharedmem的处理器可以继续执行
//----------------------------------------------------------------
//        DECL_FUNC(nlck)        //解锁
//        DECL_FUNC(slp)        //处理器睡眠
//        DECL_FUNC(new)        //建立新的processor
//        DECL_FUNC(del)        //删除processor

};


typedef enum _CODEENUM
{
        ENUM_CODE(not)
        ENUM_CODE(and)
        ENUM_CODE(or)
        ENUM_CODE(xor)

        ENUM_CODE(bool)

        ENUM_CODE(eq)
        ENUM_CODE(neq)
        ENUM_CODE(lrg)
        ENUM_CODE(sml)
        ENUM_CODE(leq)
        ENUM_CODE(seq)

        ENUM_CODE(add)
        ENUM_CODE(sub)
        ENUM_CODE(mul)
        ENUM_CODE(div)
        ENUM_CODE(mod)

        ENUM_CODE(eqf)
        ENUM_CODE(neqf)
        ENUM_CODE(lrgf)
        ENUM_CODE(smlf)
        ENUM_CODE(leqf)
        ENUM_CODE(seqf)

        ENUM_CODE(addf)
        ENUM_CODE(subf)
        ENUM_CODE(mulf)
        ENUM_CODE(divf)

        ENUM_CODE(mov)

        ENUM_CODE(push)
        ENUM_CODE(pop)

        ENUM_CODE(fti)
        ENUM_CODE(itf)

        ENUM_CODE(nop)
        ENUM_CODE(jmp)
        ENUM_CODE(jt)
        ENUM_CODE(jf)

        ENUM_CODE(call)
        ENUM_CODE(ret)

        ENUM_CODE(in)
        ENUM_CODE(out)

        //寄存器访问(RO)
        ENUM_CODE(ip)
        ENUM_CODE(sp)

        //机器内存管理
        ENUM_CODE(mmg)        // 通知Machine设置global内存Block数目,并分配每一个Block
        ENUM_CODE(mmp)        // 设置private内存Block数目,并分配每一个Block

        //机器和处理器控制指令
        ENUM_CODE(brr)        //障碍同步,*非*全局的
       
        _FORCE_DWORD = 0x7fffffff,

}CODEENUM;



class CMachine
{
private:

        MEM_BLOCKS_LIST                m_lstGlobalBlocks;

        ArrayList<CProcessor *> m_List;

        UInt32 m_numBarriers;

        UInt32 m_I;

public:

        Bool IsStoped()
        {
                return m_List.Count()==0;
        }

        void PerformOneProcess() //需要考虑宿主程序和虚拟机的Barrier同步问题!!!!!!!
                //或者,让StepMachine变成运行所有Processor......
                //但这样,不代表宿主程序和虚拟机Barrier 同步。。。
        {
                if(!m_List.Count())return;

                CProcessor *crrt=m_List.Get(m_I);
                if(crrt->m_bBarrier)return;
                crrt-&gterform();
                if(crrt->m_bKill) //Kill不是全局同步的,也是非预期的,如果需要,应使用Barrier
                {
                        m_List.Remove(m_I);
                        delete crrt; //需要考虑C++编码实现中,Kill和Barrier的一些问题等
                        return;
                }
                else if(crrt->m_bBarrier)
                {
                        m_numBarriers+=1;
                        if(m_numBarriers==m_List.Count())
                        {
                                m_numBarriers=0;
                                for(UInt32 j=0; j<m_List.Count(); j++)
                                        m_List.Get(j)->m_bBarrier=False;
                        }
                }

                m_I += 1;
                if(m_I == m_List.Count()) m_I = 0;
        }


        CMachine(void *p) //file stream in memory
        {
        }

        // global initialization!
        CMachine(MEM *pglobalmem,UInt32 globalsize,UInt32 globalblocks,
                        UInt32 num,ADDR_REGISTER *startIP,MEM **mem,UInt32 *size,UInt32 *blocks)
        {
                m_lstGlobalBlocks.Resize(globalblocks);
                for(UInt32 gb=0; gb<globalblocks; gb++)
                        m_lstGlobalBlocks.Set(gb,new MEM[BLOCK_SIZE]);

                for(UInt32 gi=0; gi<globalsize; gi++)
                {
                        *(  m_lstGlobalBlocks.Get(GLOBAL_BLOCK_INDEX(gi)) + ADDR_IN_BLOCK(gi) ) = pglobalmem[gi];
                }

                for(UInt32 i=0; i<num; i++)
                        m_List.Add(new CProcessor(&m_lstGlobalBlocks,startIP,mem,size,blocks));

                m_I=0; m_numBarriers=0;
        }

};


/*

#include <objbase.h>

interface IStdPort;


// {D459A659-E9DF-42fa-99BA-E6B0B31A0D01}
DEFINE_GUID(IID_IStdPort,
0xd459a659, 0xe9df, 0x42fa, 0x99, 0xba, 0xe6, 0xb0, 0xb3, 0x1a, 0xd, 0x1);


// {5C55A2D6-5BDF-4ee4-876D-6C724016AB30}
DEFINE_GUID(CLSID_CMachine,
0x5c55a2d6, 0x5bdf, 0x4ee4, 0x87, 0x6d, 0x6c, 0x72, 0x40, 0x16, 0xab, 0x30);

DECLARE_INTERFACE_(IMachine,IDispatch) // VB supported

class CMachine:public IStdPort
{
};

class CMachineFactory:public IClassFactory
{
};

*/


} // end of namespace vm
} // end of namespace inst


#endif

362

主题

3023

帖子

3553

积分

论坛元老

Rank: 8Rank: 8

积分
3553
 楼主| 发表于 2008-5-15 02:26:00 | 显示全部楼层

Re: 正在编写 并行计算 虚拟机 (付 源码)

        // 全局内存
        MEM gmem[100] =
        {
                // 一个全局函数
                // gFunc( void (*pf)(void) );
                code_out, 0, 11111,                        // out 11111
               
                code_sp, 1, 50,                                // sp [50] ; 读取栈顶指针SP 到 [50]
                code_sub, 1,51, 1,50, 0,1,        // sub [51], [50], 0 ; 第一个参数(pf)的指针 到 [51]
                code_mov, 1,61, 2,51,                // mov [61], *[51] ; 取得第一个参数(pf) 存入 [61]

                code_call, 1,61,                        // call [61] ; (*pf)(void)
               
                code_out, 0, 22222,                        // out 22222

                code_ret,                                        // ret
        };
       

#define PRI(x)        (PRIVATE_START_ADDR+(x))
        // 第0个处理器的初始内存(私有内存,从0x8000000开始)
        MEM p0_mem[100] =
        {
                // data
/*8*/        0,1,2,3,4,5,6,7,
                // code
/*7*/        code_add, 1,PRI(0), 1,PRI(2), 1,PRI(3),                // add [80000000H], [80000002H], [80000003H]
/*7*/        code_mul, 1,PRI(1), 1,PRI(0), 0,100,                // mul [80000001H], [80000000H], 100
/*3*/        code_out, 1,PRI(1),                                                        // out [80000001H]

/*3*/        code_push, 0,PRI(40), /*函数指针*/                        // push 80000040H
/*3*/        code_call, 0,0x0,                                                        // jmp 00000000H
/*3*/        code_pop, 1, PRI(0),                                                // pop [80000000H]

/*3*/        code_out, 0,12345,                                                        // out 12345
               
                37,38,39,  

                // 回调函数
                code_out, 0, 999,
                code_out, 0, 999,
                code_ret,
        };
sf_200851522612.jpg

45

主题

1163

帖子

1165

积分

金牌会员

Rank: 6Rank: 6

积分
1165
发表于 2008-5-15 10:26:00 | 显示全部楼层

Re:正在编写 并行计算 虚拟机 (付 源码)

都写出虚拟机来了,支持一下

362

主题

3023

帖子

3553

积分

论坛元老

Rank: 8Rank: 8

积分
3553
 楼主| 发表于 2008-5-15 16:08:00 | 显示全部楼层

Re:正在编写 并行计算 虚拟机 (付 源码)

并行虚拟机,难度在于内存管理,全局barrier同步

惨阿,还没有写汇编器,直接手工输入机器码。。。

上面的代码创建了1个处理器,1个全局函数,1个私有回调函数。

51

主题

134

帖子

140

积分

注册会员

Rank: 2

积分
140
发表于 2008-5-16 00:16:00 | 显示全部楼层

Re:正在编写 并行计算 虚拟机 (付 源码)

。。。先写虚拟机是个错误。。。本人深有体会。。。几千行代码白写了。。。还是先写汇编器为好

362

主题

3023

帖子

3553

积分

论坛元老

Rank: 8Rank: 8

积分
3553
 楼主| 发表于 2008-5-19 04:19:00 | 显示全部楼层

Re:正在编写 并行计算 虚拟机 (付 源码)

汇编器是极其简单的。

几千行?楼上不用宏吗?

34

主题

443

帖子

478

积分

中级会员

Rank: 3Rank: 3

积分
478
发表于 2008-5-19 12:42:00 | 显示全部楼层

Re:正在编写 并行计算 虚拟机 (付 源码)

很神奇

362

主题

3023

帖子

3553

积分

论坛元老

Rank: 8Rank: 8

积分
3553
 楼主| 发表于 2008-5-19 21:28:00 | 显示全部楼层

Re:正在编写 并行计算 虚拟机 (付 源码)

感觉需要好好增强堆栈寻址方面的指令,否则访问堆栈变量很麻烦,要先计算地址,都得用指针变量.
PS.没有寄存器,都是内存,寻址方式有:

0 - 立即数 [常数]
1 - 直接寻址 [变量]
2 - 间接寻址 [指针]
3 - 间接2次寻址 [2级指针]

51

主题

134

帖子

140

积分

注册会员

Rank: 2

积分
140
发表于 2008-5-20 01:50:00 | 显示全部楼层

Re:正在编写 并行计算 虚拟机 (付 源码)

刚刚看了下 虚拟机3000行 汇编器2500行。。。。不算头文件和其他自己写的库。。。不过功能倒挺完善。。。
DWORD temp;
double temp2;
DWORD add(DWORD* temp__);
DWORD main()
{
        MOV temp 0.0;
        FMOV64 temp2 0;
        RECALL add(DWORD* temp__);
        PUSH &temp 4;
        CALL add(DWORD* temp__);
        FADD64 temp2 5.5;
        RERET 0;
        RET;
}
DWORD add(DWORD* temp__)
{
        MOV $C1 temp__;
        MOV *C1 5;
        RERET 0;
        RET;       
}

这样的汇编代码基本没问题。。。

362

主题

3023

帖子

3553

积分

论坛元老

Rank: 8Rank: 8

积分
3553
 楼主| 发表于 2008-5-20 20:27:00 | 显示全部楼层

Re: 正在编写 并行计算 虚拟机 (付 源码)

呵呵,我主要考虑的是,并行多处理器。

为了方便,数据类型只有Float和Int32和UInt32
内存寻址的单位是4字节。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2026-1-22 11:14

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表