处理器不同编址方式、指令/数据处理方式区别

每个外设都是通过读写其寄存器来控制的。外设寄存器也称为I/O端口,通常包括:控制寄存器、状态寄存器和数据寄存器三大类。根据访问外设寄存器的不同方式,可以把CPU分成两大类。一类CPU(如ARM,MIPS,M68K,Power PC等)把这些寄存器看作内存的一部分,寄存器参与内存统一编址,访问寄存器就通过访问一般的内存指令进行,所以,这种CPU没有专门用于设备I/O的指令。这就是所谓的“I/O内存”方式。另一类CPU(典型的如X86),将外设的寄存器看成一个独立的地址空间,所以访问内存的指令不能用来访问这些寄存器,而要为对外设寄存器的读/写设置专用指令,如IN和OUT指令。这就是所谓的“ I/O端口”方式。

下面以X86的一种实现为例,该项目链接为http://zet.aluzina.org/index.php/Zet_processor。这个CPU的接口如下:

`include "defines.v"

module zet_core (
    input clk,
    input rst,

    // interrupts
    input  intr,
    output inta,
    input  nmi,
    output nmia,

    // interface
    output [19:0] cpu_adr_o,
    input  [15:0] iid_dat_i,
    input  [15:0] cpu_dat_i,
    output [15:0] cpu_dat_o,
    output        cpu_byte_o,
    input         cpu_block,
    output        cpu_mem_op,
    output        cpu_m_io,
    output        cpu_we_o,

    output [19:0] pc  // for debugging purposes
  );

从上面总线接口的定义中我们可以看到,该CPU具有独立的IO总线,总线信号如 data_in,data_out,adr_out,we等都是共用的,也就是MEM总线与IO总线复用这些信号,通过cpu_m_io来区分当前的总线操作是IO还是MEM,实际上是分时复用的。当然也可以完全复用,就是各自有独立的总线信号,这个项目实现了兼容传统8086的架构,所以是复用的。

module zet_exec (
    input         clk,
    input         rst,

    input [`IR_SIZE-1:0] ir,
    input [15:0]  off,
    input [15:0]  imm,
    output [15:0] cs,
    output [15:0] ip,
    output        of,
    output        zf,
    output        cx_zero,
    input [15:0]  memout,

    output [15:0] wr_data,
    output [19:0] addr,
    output        we,
    output        m_io,
    output        byteop,
    input         block,
    output        div_exc,
    input         wrip0,

    output        ifl,
    output        tfl,
    output        wr_ss
  );

  // Net declarations
  wire [15:0] c;
  wire [15:0] omemalu;
  wire [ 3:0] addr_a;
  wire [ 3:0] addr_c;
  wire [ 3:0] addr_d;
  wire [ 8:0] flags;
  wire [15:0] a, b, s, alu_iflags, bus_b;
  wire [31:0] aluout;
  wire [3:0]  addr_b;
  wire [2:0]  t, func;
  wire [1:0]  addr_s;
  wire        wrfl, high, memalu, r_byte, c_byte;
  wire        wr, wr_reg;
  wire        wr_cnd;
  wire        jmp;
  wire        b_imm;
  wire  [8:0] iflags, oflags;
  wire  [4:0] logic_flags;
  wire        alu_word;
  wire        a_byte;
  wire        b_byte;
  wire        wr_high;
  wire        dive;

  // Module instances
  zet_alu alu( {c, a }, bus_b, aluout, t, func, alu_iflags, oflags,
               alu_word, s, off, clk, dive);
  zet_regfile regfile (
        a, b, c, cs, ip, {aluout[31:16], omemalu}, s, flags, wr_reg, wrfl,
                wr_high, clk, rst, addr_a, addr_b, addr_c, addr_d, addr_s, iflags,
                ~byteop, a_byte, b_byte, c_byte, cx_zero, wrip0);
  zet_jmp_cond jmp_cond (logic_flags, addr_b, addr_c[0], c, jmp);

  // Assignments
  assign addr_s = ir[1:0];
  assign addr_a = ir[5:2];
  assign addr_b = ir[9:6];
  assign addr_c = ir[13:10];
  assign addr_d = ir[17:14];
  assign wrfl   = ir[18];
  assign we     = ir[19];
  assign wr     = ir[20];
  assign wr_cnd = ir[21];
  assign high   = ir[22];
  assign t      = ir[25:23];
  assign func   = ir[28:26];
  assign byteop = ir[29];
  assign memalu = ir[30];
  assign m_io   = ir[32];
  assign b_imm  = ir[33];
  assign r_byte = ir[34];
  assign c_byte = ir[35];

  assign omemalu = memalu ? aluout[15:0] : memout;
  assign bus_b   = b_imm ? imm : b;

  assign addr = aluout[19:0];
  assign wr_data = c;
  assign wr_reg  = (wr | (jmp & wr_cnd)) && !block && !div_exc;
  assign wr_high = high && !block && !div_exc;
  assign of  = flags[8];
  assign ifl = flags[6];
  assign tfl = flags[5];
  assign zf  = flags[3];

  assign iflags = oflags;
  assign alu_iflags = { 4‘b1111, flags[8:3], 1‘b0, flags[2], 1‘b0, flags[1],
                        1‘b1, flags[0] };
  assign logic_flags = { flags[8], flags[4], flags[3], flags[1], flags[0] };

  assign alu_word = (t==3‘b011) ? ~r_byte : ~byteop;
  assign a_byte = (t==3‘b011 && func[1]) ? 1‘b0 : r_byte;
  assign b_byte = r_byte;
  assign div_exc = dive && wr;

  assign wr_ss = (addr_d == 4‘b1010) && wr;

endmodule

这部分代码可以看出,addr的计算来源只有一个,也就是他并不区分指令地址和数据地址,因此是冯诺依曼结构的处理器。

下面以OpenRISC无MMU和浮点运算单元的精简版本AltOR32处理器来说明统一编址的CPU总线接口形式。

(1)冯诺依曼结构,读取数据的接口和读取指令的接口在一起的,代码如下:

module altor32_lite
(
    // General
    input               clk_i /*verilator public*/,
    input               rst_i /*verilator public*/,

    // Maskable interrupt
    input               intr_i /*verilator public*/,

    // Unmaskable interrupt
    input               nmi_i /*verilator public*/,

    // Memory interface
    output reg [31:0]   mem_addr_o /*verilator public*/,
    input [31:0]        mem_dat_i /*verilator public*/,
    output reg [31:0]   mem_dat_o /*verilator public*/,
    output reg          mem_cyc_o /*verilator public*/,
    output reg          mem_stb_o /*verilator public*/,
    output reg          mem_we_o /*verilator public*/,
    output reg [3:0]    mem_sel_o /*verilator public*/,
    input               mem_ack_i/*verilator public*/
);
.
.
.
.
//-----------------------------------------------------------------
// Next State Logic
//-----------------------------------------------------------------
reg [3:0] next_state_r;
always @ *
begin
    next_state_r = state_q;

    case (state_q)
    //-----------------------------------------
    // IDLE -
    //-----------------------------------------
    STATE_IDLE :
    begin
        if (enable_i)
            next_state_r    = STATE_FETCH;
    end
    //-----------------------------------------
    // FETCH - Fetch line from memory
    //-----------------------------------------
    STATE_FETCH :
    begin
        next_state_r    = STATE_FETCH_WAIT;
    end
    //-----------------------------------------
    // FETCH_WAIT - Wait for read responses
    //-----------------------------------------
    STATE_FETCH_WAIT:
    begin
        // Read from memory complete
        if (mem_ack_i)
            next_state_r = STATE_EXEC;
    end
    //-----------------------------------------
    // EXEC
    //-----------------------------------------
    STATE_EXEC :
    begin
        if (load_inst_r || store_inst_r)
            next_state_r    = STATE_MEM;
        else
            next_state_r    = STATE_WRITE_BACK;
    end
    //-----------------------------------------
    // MEM
    //-----------------------------------------
    STATE_MEM :
    begin
        // Read from memory complete
        if (mem_ack_i)
            next_state_r = STATE_FETCH;
    end
    //-----------------------------------------
    // WRITE_BACK
    //-----------------------------------------
    STATE_WRITE_BACK :
    begin
        if (enable_i)
            next_state_r    = STATE_FETCH;
    end
    default:
        ;
   endcase
end
.
.
.
.
//-----------------------------------------------------------------
// Memory Access / Instruction Fetch
//-----------------------------------------------------------------
always @ (posedge rst_i or posedge clk_i )
begin
   if (rst_i == 1‘b1)
   begin
        mem_addr_o      <= 32‘h00000000;
        mem_dat_o       <= 32‘h00000000;
        mem_sel_o       <= 4‘b0;
        mem_we_o        <= 1‘b0;
        mem_stb_o       <= 1‘b0;
        mem_cyc_o       <= 1‘b0;

        opcode_q        <= 32‘h00000000;
        mem_offset_q    <= 2‘b0;
   end
   else
   begin
        case (state_q)

            //-----------------------------------------
            // FETCH - Issue instruction fetch
            //-----------------------------------------
            STATE_FETCH :
            begin
                // Start fetch from memory
                mem_addr_o  <= pc_q;
                mem_stb_o   <= 1‘b1;
                mem_we_o    <= 1‘b0;
                mem_cyc_o   <= 1‘b1;
            end
            //-----------------------------------------
            // FETCH_WAIT - Wait for response
            //-----------------------------------------
            STATE_FETCH_WAIT :
            begin
                // Data ready from memory?
                if (mem_ack_i)
                begin
                    opcode_q    <= mem_dat_i;
                    mem_cyc_o   <= 1‘b0;
                end
            end
            //-----------------------------------------
            // EXEC - Issue read / write
            //-----------------------------------------
            STATE_EXEC :
            begin
            `ifdef CONF_CORE_TRACE
                $display("%08x: Execute 0x%08x", pc_q, opcode_q);
                $display(" rA[%d] = 0x%08x", ra_w, reg_ra_r);
                $display(" rB[%d] = 0x%08x", rb_w, reg_rb_r);
            `endif

                case (1‘b1)
                 // l.lbs l.lhs l.lws l.lbz l.lhz l.lwz
                 load_inst_r:
                 begin
                     mem_addr_o      <= {mem_addr_r[31:2], 2‘b0};
                     mem_offset_q    <= mem_addr_r[1:0];
                     mem_dat_o       <= 32‘h00000000;
                     mem_sel_o       <= 4‘b1111;
                     mem_we_o        <= 1‘b0;
                     mem_stb_o       <= 1‘b1;
                     mem_cyc_o       <= 1‘b1;   

      `ifdef CONF_CORE_DEBUG
                     $display(" Load from 0x%08x to R%d", mem_addr_r, rd_w);
      `endif
                 end

                 inst_sb_w: // l.sb
                 begin
                     mem_addr_o      <= {mem_addr_r[31:2], 2‘b0};
                     mem_offset_q    <= mem_addr_r[1:0];
                     case (mem_addr_r[1:0])
                         2‘b00 :
                         begin
                             mem_dat_o       <= {reg_rb_r[7:0],24‘h000000};
                             mem_sel_o       <= 4‘b1000;
                             mem_we_o        <= 1‘b1;
                             mem_stb_o       <= 1‘b1;
                             mem_cyc_o       <= 1‘b1;
                         end
                         2‘b01 :
                         begin
                             mem_dat_o       <= {{8‘h00,reg_rb_r[7:0]},16‘h0000};
                             mem_sel_o       <= 4‘b0100;
                             mem_we_o        <= 1‘b1;
                             mem_stb_o       <= 1‘b1;
                             mem_cyc_o       <= 1‘b1;
                         end
                         2‘b10 :
                         begin
                             mem_dat_o       <= {{16‘h0000,reg_rb_r[7:0]},8‘h00};
                             mem_sel_o       <= 4‘b0010;
                             mem_we_o        <= 1‘b1;
                             mem_stb_o       <= 1‘b1;
                             mem_cyc_o       <= 1‘b1;
                         end
                         2‘b11 :
                         begin
                             mem_dat_o       <= {24‘h000000,reg_rb_r[7:0]};
                             mem_sel_o       <= 4‘b0001;
                             mem_we_o        <= 1‘b1;
                             mem_stb_o       <= 1‘b1;
                             mem_cyc_o       <= 1‘b1;
                         end
                         default :
                            ;
                     endcase
                 end

                inst_sh_w: // l.sh
                begin
                     mem_addr_o      <= {mem_addr_r[31:2], 2‘b0};
                     mem_offset_q    <= mem_addr_r[1:0];
                     case (mem_addr_r[1:0])
                         2‘b00 :
                         begin
                             mem_dat_o       <= {reg_rb_r[15:0],16‘h0000};
                             mem_sel_o       <= 4‘b1100;
                             mem_we_o        <= 1‘b1;
                             mem_stb_o       <= 1‘b1;
                             mem_cyc_o       <= 1‘b1;
                         end
                         2‘b10 :
                         begin
                             mem_dat_o       <= {16‘h0000,reg_rb_r[15:0]};
                             mem_sel_o       <= 4‘b0011;
                             mem_we_o        <= 1‘b1;
                             mem_stb_o       <= 1‘b1;
                             mem_cyc_o       <= 1‘b1;
                         end
                         default :
                            ;
                     endcase
                end

                inst_sw_w: // l.sw
                begin
                     mem_addr_o      <= {mem_addr_r[31:2], 2‘b0};
                     mem_offset_q    <= mem_addr_r[1:0];
                     mem_dat_o       <= reg_rb_r;
                     mem_sel_o       <= 4‘b1111;
                     mem_we_o        <= 1‘b1;
                     mem_stb_o       <= 1‘b1;
                     mem_cyc_o       <= 1‘b1;

      `ifdef CONF_CORE_DEBUG
                     $display(" Store R%d to 0x%08x = 0x%08x", rb_w, {mem_addr_r[31:2],2‘b00}, reg_rb_r);
      `endif
                end
                default:
                    ;
             endcase
            end
            //-----------------------------------------
            // MEM - Wait for response
            //-----------------------------------------
            STATE_MEM :
            begin
                // Data ready from memory?
                if (mem_ack_i)
                begin
                    mem_cyc_o   <= 1‘b0;
                end
            end
            default:
                ;
           endcase
   end
end

该实现是一个典型的5级流水线处理器,下方的部分是访存部分的状态机逻辑实现,这部分的代码描述了 Memory Access / Instruction Fetch的操作,是通过唯一的总线端口进行的。

(2)哈佛结构,读取数据的接口和读取指令的接口分开,代码如下:

//-----------------------------------------------------------------
// Module - AltOR32 CPU (Pipelined Wishbone Interfaces)
//-----------------------------------------------------------------
module altor32
(
    // General
    input               clk_i,
    input               rst_i,

    input               intr_i,
    input               nmi_i,
    output              fault_o,
    output              break_o,

    // Instruction memory
    output [31:0]       imem_addr_o,
    input [31:0]        imem_dat_i,
    output [2:0]        imem_cti_o,
    output              imem_cyc_o,
    output              imem_stb_o,
    input               imem_ack_i,  

    // Data memory
    output [31:0]       dmem_addr_o,
    output [31:0]       dmem_dat_o,
    input [31:0]        dmem_dat_i,
    output [3:0]        dmem_sel_o,
    output [2:0]        dmem_cti_o,
    output              dmem_cyc_o,
    output              dmem_we_o,
    output              dmem_stb_o,
    input               dmem_ack_i
);
.
.
.
//-----------------------------------------------------------------
// Module - Wishbone fetch unit
//-----------------------------------------------------------------
always @ (posedge rst_i or posedge clk_i )
begin
   if (rst_i == 1‘b1)
   begin
        wbm_addr_o      <= 32‘h00000000;
        wbm_cti_o       <= 3‘b0;
        wbm_stb_o       <= 1‘b0;
        wbm_cyc_o       <= 1‘b0;

        fetch_word_q    <= {FETCH_WORDS_W{1‘b0}};
        resp_word_q     <= {FETCH_WORDS_W{1‘b0}};
   end
   else
   begin
        // Idle
        if (!wbm_cyc_o)
        begin
            if (fetch_i)
            begin
                if (burst_i)
                begin
                    wbm_addr_o      <= {address_i[31:FETCH_BYTES_W], {FETCH_BYTES_W{1‘b0}}};
                    fetch_word_q    <= {FETCH_WORDS_W{1‘b0}};
                    resp_word_q     <= {FETCH_WORDS_W{1‘b0}};

                    // Incrementing linear burst
                    wbm_cti_o       <= WB_CTI_BURST;
                end
                else
                begin
                    wbm_addr_o      <= address_i;
                    resp_word_q     <= address_i[FETCH_BYTES_W-1:2];

                    // Single fetch
                    wbm_cti_o       <= WB_CTI_FINAL;
                end

                // Start fetch from memory
                wbm_stb_o           <= 1‘b1;
                wbm_cyc_o           <= 1‘b1;
            end
        end
        // Access in-progress
        else
        begin
            // Command accepted
            if (~wbm_stall_i)
            begin
                // Fetch next word for line
                if (wbm_cti_o != WB_CTI_FINAL)
                begin
                    wbm_addr_o      <= {wbm_addr_o[31:FETCH_BYTES_W], next_word_w, 2‘b0};
                    fetch_word_q    <= next_word_w;

                    // Final word to read?
                    if (penultimate_word_w)
                        wbm_cti_o   <= WB_CTI_FINAL;
                end
                // Fetch complete
                else
                    wbm_stb_o       <= 1‘b0;
            end

            // Response
            if (wbm_ack_i)
                resp_word_q         <= resp_word_q + 1‘b1;

            // Last response?
            if (final_o)
                wbm_cyc_o           <= 1‘b0;
        end
   end
end
.
.
.
.
//-----------------------------------------------------------------
// Module - Data Cache Memory Interface
//-----------------------------------------------------------------
always @ *
begin
    next_state_r = state;

    case (state)
    //-----------------------------------------
    // IDLE
    //-----------------------------------------
    STATE_IDLE :
    begin
        // Perform cache evict (write)
        if (evict_i)
            next_state_r    = STATE_WRITE_SETUP;
        // Perform cache fill (read)
        else if (fill_i)
            next_state_r    = STATE_FETCH;
        // Read/Write single
        else if (rd_single_i | (|wr_single_i))
            next_state_r    = STATE_MEM_SINGLE;
    end
    //-----------------------------------------
    // FETCH - Fetch line from memory
    //-----------------------------------------
    STATE_FETCH :
    begin
        // Line fetch complete?
        if (~mem_stall_i && request_idx == {CACHE_LINE_WORDS_IDX_MAX{1‘b1}})
            next_state_r    = STATE_FETCH_WAIT;
    end
    //-----------------------------------------
    // FETCH_WAIT - Wait for read responses
    //-----------------------------------------
    STATE_FETCH_WAIT:
    begin
        // Read from memory complete
        if (mem_ack_i && response_idx == {CACHE_LINE_WORDS_IDX_MAX{1‘b1}})
            next_state_r = STATE_IDLE;
    end
    //-----------------------------------------
    // WRITE_SETUP - Wait for data from cache
    //-----------------------------------------
    STATE_WRITE_SETUP :
        next_state_r    = STATE_WRITE;
    //-----------------------------------------
    // WRITE - Write word to memory
    //-----------------------------------------
    STATE_WRITE :
    begin
        // Line write complete?
        if (~mem_stall_i && request_idx == {CACHE_LINE_WORDS_IDX_MAX{1‘b1}})
            next_state_r = STATE_WRITE_WAIT;
        // Fetch next word for line
        else if (~mem_stall_i | ~mem_stb_o)
            next_state_r = STATE_WRITE_SETUP;
    end
    //-----------------------------------------
    // WRITE_WAIT - Wait for write to complete
    //-----------------------------------------
    STATE_WRITE_WAIT:
    begin
        // Write to memory complete
        if (mem_ack_i && response_idx == {CACHE_LINE_WORDS_IDX_MAX{1‘b1}})
            next_state_r = STATE_IDLE;
    end
    //-----------------------------------------
    // MEM_SINGLE - Single access to memory
    //-----------------------------------------
    STATE_MEM_SINGLE:
    begin
        // Data ready from memory?
        if (mem_ack_i)
            next_state_r  = STATE_IDLE;
    end
    default:
        ;
   endcase
end

上面摘录了不同阶段的代码,首先是CPU总线接口,有专门的指令总线和数据总线,下面是指令读取的状态机逻辑中的操作,最后部分是数据读写的逻辑操作。

时间: 2024-10-15 20:13:38

处理器不同编址方式、指令/数据处理方式区别的相关文章

PLSQL_标准删除的方式Delete/Drop/Truncate区别和比较(概念)

2014-06-02 BaoXinjian 一.总论 1. Delete 2. Drop 3. Truncate 4. 例子:一亿条数据中如何删除其中的不符合条件的9999万条,保留剩余部分 二.具体分析 1. Delete / Drop / Truncate 删除方式的区别 (1).删除数据及表定义 truncate和 delete只删除数据不删除表的结构(定义)          drop语句将删除表的结构被依赖的约束(constrain),触发器(trigger),索引(index); 依

HTML提交方式post和get区别(实验)

HTML提交方式post和get区别(实验) 一.post和get区别 get提交,提交的信息都显示在地址栏中. post提交,提交的信息不显示地址栏中,显示在消息体中. 二.客户端代码 <!DOCTYPE html> <html> <head> <title>Form.html</title> <meta name="keywords" content="keyword1,keyword2,keyword3&

表单_post提交方式和get的区别,元素集

提交方式及表单域的name属性 使用form表单一种是post提交方式,一种是get提交方式,它们以method属性来定义,如果没有指定method属性,默认get方式提交. 表单域必须配合name属性才可以将数据提交到服务器 post方式与get方式的区别: 一.安全性 get方式不安全,以URL方式进行提交.(密码会显示在地址栏) post以请求实体提交,不会显示地址栏,足够安全 二.提交大小限制 get方式提交的内容有限,一个地址栏放不了多少东西,1k左右 post大小无限制,可以放大文件

文本与二进制方式打开文件的区别

文本与二进制方式打开文件的区别 文本文件也叫做ASCII码文件,与以‘文本方式’打开文件不是同一个概念!文本文件存储的是ASSCII码字符,即存储在磁盘上只占用二进制的0x20--0x7e.另外,还有回车(0x0d),换行(0x0a),TAB(0x09)等,所以有可压缩的空间. 换行和回车是不同的,而且在不同的操作系统,解释也不相同.‘\n’一般会操作系统被翻译成"行的结束",即LF(Line-Feed):‘\r’会被翻译成"回?,即CR(Cariage-Return) 回车

非接触IC卡中typeA卡和typeB卡的区别--总结,二者的调制方式和编码方式不同

非接触IC卡中typeA卡和typeB卡的区别--总结,二者的调制方式和编码方式不同 1.非接触式IC卡的国际规范ISO/IEC14443的由来? 在非接触式IC卡的发展过程中,这些问题逐渐被解决并形成通用的标准,体现在现在的射频IC卡的设计上,国际标准化组织(ISO)和国际电子技术委员会(IEC)为期制定了相应的非接触式IC卡的国际标准--ISO/IEC14443. 2.ISO/IEC14443中的主要内容及typeA,typeB卡的由来 ISO/IEC14443标准包括四个部分: 第一部分I

前缀方式增1和后缀方式增1的区别

增量运算符++属于一元运算符,增量运算符可以出现在变量的前面作为前缀,也可以出现在变量的后面作为后缀.两者有何区别呢? 前缀方式加1 先使用前缀方式加1,并把前缀方式加1后变量的值赋值给另外一个临时变量temp. static void Main(string[] args) { int num1 = 0; while (num1 < 3) { int temp; Console.WriteLine("变量num1的值是:" + num1.ToString()); temp =

XMLHttpRequest 异步方式和同步方式

一.同步和异步区别 简单说:同步是阻塞模式,异步是非阻塞模式. 举个例子:普通B/S模式(同步)AJAX技术(异步) 同步:提交请求->等待服务器处理->处理完毕返回 这个期间客户端浏览器不能干任何事 异步: 请求通过事件触发->服务器处理(这是浏览器仍然可以作其他事情)->处理完毕 二.XMLHttpRequest 异步方式和同步方式 xmlHttp.open("GET", url, false);//同步方式请求 xmlHttp.open("GET

006_03Java解析XML之DOM方式与SAX方式

XML解析方式分为两种:DOM方式和SAX方式 DOM:Document Object Model,文档对象模型.这种方式是W3C推荐的处理XML的一种方式. SAX:Simple API for XML.这种方式不是官方标准,属于开源社区XML-DEV,几乎所有的XML解析器都支持它. XML解析开发包 JAXP:是SUN公司推出的解析标准实现. Dom4J:是开源组织推出的解析开发包. JDom:是开源组织推出的解析开发包. JAXP: JAXP:(Java API for XML Proc

mybatis mapper xml文件的导入方式和查询方式

mybatis mapper xml文件的导入方式和查询方式 ssm框架 Mybatis mapper与SQLSession的关系 每个基于MyBatis的应用都是以一个SqlSessionFactory的实例为中心的.通过SqlSessionFactory可以获得SQLSession实例,然后在其中完全包含了数据库执行SQL命令所需要的所有方法. SQLMapper是由一个Java接口和XML文件构成的,给出一定的SQL和映射规则.负责SQL的执行和返回结果. 通过SQLSession获得Ma