From e3900bd0fa01eb2ad0e3c734d1b11d0a51107002 Mon Sep 17 00:00:00 2001 From: Thomas Fleming Date: Thu, 25 Mar 2021 02:48:40 -0400 Subject: [PATCH] Finish finite state machines for page table walker --- wally-pipelined/src/ebu/ahblite.sv | 84 +++--- wally-pipelined/src/ebu/pagetablewalker.sv | 246 +++++++++++++++--- wally-pipelined/src/privileged/privileged.sv | 12 +- .../src/wally/wallypipelinedhart.sv | 3 +- 4 files changed, 270 insertions(+), 75 deletions(-) diff --git a/wally-pipelined/src/ebu/ahblite.sv b/wally-pipelined/src/ebu/ahblite.sv index 201378666..90ef018b3 100644 --- a/wally-pipelined/src/ebu/ahblite.sv +++ b/wally-pipelined/src/ebu/ahblite.sv @@ -48,7 +48,7 @@ module ahblite ( input logic [1:0] MemSizeM, // Signals from MMU input logic [`XLEN-1:0] MMUPAdr, - input logic MMUTranslate, + input logic MMUTranslate, MMUTranslationComplete, output logic [`XLEN-1:0] MMUReadPTE, output logic MMUReady, // Return from bus @@ -75,7 +75,8 @@ module ahblite ( ); logic GrantData; - logic [2:0] ISize; + logic [31:0] AccessAddress; + logic [2:0] AccessSize, PTESize, ISize; logic [`AHBW-1:0] HRDATAMasked, ReadDataM, ReadDataNewW, ReadDataOldW, WriteData; logic IReady, DReady; logic CaptureDataM; @@ -89,47 +90,69 @@ module ahblite ( // Data accesses have priority over instructions. However, if a data access comes // while an instruction read is occuring, the instruction read finishes before // the data access can take place. - typedef enum {IDLE, MEMREAD, MEMWRITE, INSTRREAD, INSTRREADC, ATOMICREAD, ATOMICWRITE} statetype; + typedef enum {IDLE, MEMREAD, MEMWRITE, INSTRREAD, INSTRREADC, ATOMICREAD, ATOMICWRITE, MMUTRANSLATE, MMUIDLE} statetype; statetype BusState, NextBusState; flopenl #(.TYPE(statetype)) busreg(HCLK, ~HRESETn, 1'b1, NextBusState, IDLE, BusState); always_comb case (BusState) - IDLE: if (AtomicM[1]) NextBusState = ATOMICREAD; - else if (MemReadM) NextBusState = MEMREAD; // Memory has pirority over instructions - else if (MemWriteM) NextBusState = MEMWRITE; - else if (InstrReadF) NextBusState = INSTRREAD; - else NextBusState = IDLE; - ATOMICREAD: if (~HREADY) NextBusState = ATOMICREAD; - else NextBusState = ATOMICWRITE; - ATOMICWRITE: if (~HREADY) NextBusState = ATOMICWRITE; - else if (InstrReadF) NextBusState = INSTRREAD; - else NextBusState = IDLE; - MEMREAD: if (~HREADY) NextBusState = MEMREAD; - else if (InstrReadF) NextBusState = INSTRREADC; - else NextBusState = IDLE; - MEMWRITE: if (~HREADY) NextBusState = MEMWRITE; - else if (InstrReadF) NextBusState = INSTRREAD; - else NextBusState = IDLE; + IDLE: if (MMUTranslate) NextBusState = MMUTRANSLATE; + else if (AtomicM[1]) NextBusState = ATOMICREAD; + else if (MemReadM) NextBusState = MEMREAD; // Memory has priority over instructions + else if (MemWriteM) NextBusState = MEMWRITE; + else if (InstrReadF) NextBusState = INSTRREAD; + else NextBusState = IDLE; + MMUTRANSLATE: if (~HREADY) NextBusState = MMUTRANSLATE; + else NextBusState = MMUIDLE; + // *** Could the MMUIDLE state just be the normal idle state? + // Do we trust MMUTranslate to be high exactly when we need translation? + MMUIDLE: if (~MMUTranslationComplete) + NextBusState = MMUTRANSLATE; + else if (AtomicM[1]) NextBusState = ATOMICREAD; + else if (MemReadM) NextBusState = MEMREAD; // Memory has priority over instructions + else if (MemWriteM) NextBusState = MEMWRITE; + else if (InstrReadF) NextBusState = INSTRREAD; + else NextBusState = IDLE; + ATOMICREAD: if (~HREADY) NextBusState = ATOMICREAD; + else NextBusState = ATOMICWRITE; + ATOMICWRITE: if (~HREADY) NextBusState = ATOMICWRITE; + else if (InstrReadF) NextBusState = INSTRREAD; + else NextBusState = IDLE; + MEMREAD: if (~HREADY) NextBusState = MEMREAD; + else if (InstrReadF) NextBusState = INSTRREADC; + else NextBusState = IDLE; + MEMWRITE: if (~HREADY) NextBusState = MEMWRITE; + else if (InstrReadF) NextBusState = INSTRREAD; + else NextBusState = IDLE; INSTRREAD: - if (~HREADY) NextBusState = INSTRREAD; - else NextBusState = IDLE; // if (InstrReadF still high) - INSTRREADC: if (~HREADY) NextBusState = INSTRREADC; // "C" for "competing", meaning please don't mess up the memread in the W stage. - else NextBusState = IDLE; + if (~HREADY) NextBusState = INSTRREAD; + else NextBusState = IDLE; // if (InstrReadF still high) + INSTRREADC: if (~HREADY) NextBusState = INSTRREADC; // "C" for "competing", meaning please don't mess up the memread in the W stage. + else NextBusState = IDLE; endcase // stall signals assign #2 DataStall = (NextBusState == MEMREAD) || (NextBusState == MEMWRITE) || - (NextBusState == ATOMICREAD) || (NextBusState == ATOMICWRITE); - assign #1 InstrStall = (NextBusState == INSTRREAD) || (NextBusState == INSTRREADC); - + (NextBusState == ATOMICREAD) || (NextBusState == ATOMICWRITE) || + (NextBusState == MMUTRANSLATE) || (NextBusState == MMUIDLE); + // *** Could get finer grained stalling if we distinguish between MMU + // instruction address translation and data address translation + assign #1 InstrStall = (NextBusState == INSTRREAD) || (NextBusState == INSTRREADC) || + (NextBusState == MMUTRANSLATE) || (NextBusState == MMUIDLE); + // bus outputs assign #1 GrantData = (NextBusState == MEMREAD) || (NextBusState == MEMWRITE) || - (NextBusState == ATOMICREAD) || (NextBusState == ATOMICWRITE); - assign #1 HADDR = (GrantData) ? MemPAdrM[31:0] : InstrPAdrF[31:0]; + (NextBusState == ATOMICREAD) || (NextBusState == ATOMICWRITE); + assign #1 AccessAddress = (GrantData) ? MemPAdrM[31:0] : InstrPAdrF[31:0]; + assign #1 HADDR = (MMUTranslate) ? MMUPAdr[31:0] : AccessAddress; + generate + if (`XLEN == 32) assign PTESize = 3'b010; // in rv32, PTEs are 4 bytes + else assign PTESize = 3'b011; // in rv64, PTEs are 8 bytes + endgenerate assign ISize = 3'b010; // 32 bit instructions for now; later improve for filling cache with full width; ignored on reads anyway - assign #1 HSIZE = GrantData ? {1'b0, MemSizeM} : ISize; + assign #1 AccessSize = (GrantData) ? {1'b0, MemSizeM} : ISize; + assign #1 HSIZE = (MMUTranslate) ? PTESize : AccessSize; assign HBURST = 3'b000; // Single burst only supported; consider generalizing for cache fillsfH assign HPROT = 4'b0011; // not used; see Section 3.7 assign HTRANS = (NextBusState != IDLE) ? 2'b10 : 2'b00; // NONSEQ if reading or writing, IDLE otherwise @@ -145,7 +168,10 @@ module ahblite ( // Route signals to Instruction and Data Caches // *** assumes AHBW = XLEN + assign #1 MMUReady = (NextBusState == MMUIDLE); + assign InstrRData = HRDATA; + assign MMUReadPTE = HRDATA; assign ReadDataM = HRDATAMasked; // changed from W to M dh 2/7/2021 assign CaptureDataM = ((BusState == MEMREAD) && (NextBusState != MEMREAD)) || ((BusState == ATOMICREAD) && (NextBusState == ATOMICWRITE)); diff --git a/wally-pipelined/src/ebu/pagetablewalker.sv b/wally-pipelined/src/ebu/pagetablewalker.sv index 2ba2b78c6..16bb9ae26 100644 --- a/wally-pipelined/src/ebu/pagetablewalker.sv +++ b/wally-pipelined/src/ebu/pagetablewalker.sv @@ -32,25 +32,29 @@ module pagetablewalker ( input logic [`XLEN-1:0] SATP_REGW, + input logic MemWriteM, input logic ITLBMissF, DTLBMissM, input logic [`XLEN-1:0] PCF, MemAdrM, output logic [`XLEN-1:0] PageTableEntryF, PageTableEntryM, output logic ITLBWriteF, DTLBWriteM, // *** handshake to tlbs probably not needed, since stalls take effect - // output logic TranslationComplete + output logic MMUTranslationComplete, // Signals from and to ahblite input logic [`XLEN-1:0] MMUReadPTE, input logic MMUReady, output logic [`XLEN-1:0] MMUPAdr, - output logic MMUTranslate + output logic MMUTranslate, + + // Faults + output logic InstrPageFaultM, LoadPageFaultM, StorePageFaultM ); logic SvMode; logic [`PPN_BITS-1:0] BasePageTablePPN; - logic [`XLEN-1:0] DirectInstrPTE, DirectMemPTE; + logic [`XLEN-1:0] DirectInstrPTE, DirectMemPTE, TranslationVAdr; logic [9:0] DirectPTEFlags = {2'b0, 8'b00001111}; @@ -73,71 +77,233 @@ module pagetablewalker ( end endgenerate - flopenr #(`XLEN) instrpte(clk, reset, ITLBMissF, DirectInstrPTE, PageTableEntryF); - flopenr #(`XLEN) datapte(clk, reset, DTLBMissM, DirectMemPTE, PageTableEntryM); + //flopenr #(`XLEN) instrpte(clk, reset, ITLBMissF, DirectInstrPTE, PageTableEntryF); + //flopenr #(`XLEN) datapte(clk, reset, DTLBMissM, DirectMemPTE, PageTableEntryM); - flopr #(1) iwritesignal(clk, reset, ITLBMissF, ITLBWriteF); - flopr #(1) dwritesignal(clk, reset, DTLBMissM, DTLBWriteM); + //flopr #(1) iwritesignal(clk, reset, ITLBMissF, ITLBWriteF); + //flopr #(1) dwritesignal(clk, reset, DTLBMissM, DTLBWriteM); + + // Prefer data address translations over instruction address translations + assign TranslationVAdr = (DTLBMissM) ? MemAdrM : PCF; + assign MMUTranslate = DTLBMissM || ITLBMissF; -/* generate if (`XLEN == 32) begin assign SvMode = SATP_REGW[31]; - logic VPN1 [9:0] = TranslationVAdr[31:22]; - logic VPN0 [9:0] = TranslationVAdr[21:12]; // *** could optimize by not passing offset? + logic [9:0] VPN1 = TranslationVAdr[31:22]; + logic [9:0] VPN0 = TranslationVAdr[21:12]; // *** could optimize by not passing offset? - logic TranslationPAdr [33:0]; + logic [33:0] TranslationPAdr; + logic [21:0] CurrentPPN; - typedef enum {IDLE, DATA_LEVEL1, DATA_LEVEL0, DATA_LEAF, DATA FAULT} statetype; + logic Dirty, Accessed, Global, User, + Executable, Writable, Readable, Valid; + logic ValidPTE, AccessAlert, MegapageMisaligned, BadMegapage, LeafPTE; + + typedef enum {IDLE, LEVEL1, LEVEL0, LEAF, FAULT} statetype; statetype WalkerState, NextWalkerState; - always_ff @(posedge HCLK, negedge HRESETn) - if (~HRESETn) WalkerState <= #1 IDLE; - else WalkerState <= #1 NextWalkerState; + // *** Do we need a synchronizer here for walker to talk to ahblite? + flopenl #(.TYPE(statetype)) mmureg(clk, reset, 1'b1, NextWalkerState, IDLE, WalkerState); always_comb begin - NextWalkerState = 'X; case (WalkerState) - IDLE: if (TLBMissM) NextWalkerState = LEVEL1; - else NextWalkerState = IDLE; - LEVEL1: if (HREADY && ValidEntry) NextWalkerState = LEVEL0; - else if (HREADY) NextWalkerState = FAULT; - else NextWalkerState = LEVEL1; - LEVEL2: if (HREADY && ValidEntry) NextWalkerState = LEAF; - else if (HREADY) NextWalkerState = FAULT; - else NextWalkerState = LEVEL2; - LEAF: NextWalkerState = IDLE; + IDLE: if (MMUTranslate) NextWalkerState = LEVEL1; + else NextWalkerState = IDLE; + LEVEL1: if (~MMUReady) NextWalkerState = LEVEL1; + // else if (~ValidPTE || (LeafPTE && BadMegapage)) + // NextWalkerState = FAULT; + // *** Leave megapage implementation for later + // else if (ValidPTE && LeafPTE) NextWalkerState = LEAF; + else if (ValidPTE && ~LeafPTE) NextWalkerState = LEVEL0; + else NextWalkerState = FAULT; + LEVEL0: if (~MMUReady) NextWalkerState = LEVEL0; + else if (ValidPTE && LeafPTE && ~AccessAlert) + NextWalkerState = LEAF; + else NextWalkerState = FAULT; + LEAF: if (MMUTranslate) NextWalkerState = LEVEL1; + else NextWalkerState = IDLE; + FAULT: if (MMUTranslate) NextWalkerState = LEVEL1; + else NextWalkerState = IDLE; endcase end - always_ff @(posedge HCLK, negedge HRESETn) - if (~HRESETn) begin + // unswizzle PTE bits + assign {Dirty, Accessed, Global, User, + Executable, Writable, Readable, Valid} = MMUReadPTE[7:0]; + + // A megapage is a Level 1 leaf page. This page must have zero PPN[0]. + assign MegapageMisaligned = |(CurrentPPN[9:0]); + assign LeafPTE = Executable | Writable | Readable; + assign ValidPTE = Valid && ~(Writable && ~Readable); + assign AccessAlert = ~Accessed || (MemWriteM && ~Dirty); + assign BadMegapage = MegapageMisaligned || AccessAlert; // *** Implement better access/dirty scheme + + // *** Should translate this flop block into our flop module notation + always_ff @(posedge clk, negedge reset) + if (reset) begin TranslationPAdr <= '0; PageTableEntryF <= '0; - TranslationComplete <= '0; + MMUTranslationComplete <= '0; + DTLBWriteM <= '0; + ITLBWriteF <= '0; + InstrPageFaultM <= '0; + LoadPageFaultM <= '0; + StorePageFaultM <= '0; end else begin // default values + TranslationPAdr <= '0; + PageTableEntryF <= '0; + MMUTranslationComplete <= '0; + DTLBWriteM <= '0; + ITLBWriteF <= '0; + InstrPageFaultM <= '0; + LoadPageFaultM <= '0; + StorePageFaultM <= '0; case (NextWalkerState) - LEVEL1: TranslationPAdr <= {BasePageTablePPN, VPN1, 2'b00}; - LEVEL2: TranslationPAdr <= {CurrentPPN, VPN0, 2'b00}; + LEVEL1: begin + TranslationPAdr <= {BasePageTablePPN, VPN1, 2'b00}; + end + LEVEL0: begin + TranslationPAdr <= {CurrentPPN, VPN0, 2'b00}; + end LEAF: begin - PageTableEntryF <= CurrentPageTableEntry; - TranslationComplete <= '1; - end + PageTableEntryF <= MMUReadPTE; + PageTableEntryM <= MMUReadPTE; + MMUTranslationComplete <= '1; + DTLBWriteM <= DTLBMissM; + ITLBWriteF <= ~DTLBMissM; // Prefer data over instructions + end + FAULT: begin + InstrPageFaultM <= ~DTLBMissM; + LoadPageFaultM <= DTLBMissM && ~MemWriteM; + StorePageFaultM <= DTLBMissM && MemWriteM; + end endcase end - assign #1 Translate = (NextWalkerState == LEVEL1); + // Interpret inputs from ahblite + assign CurrentPPN = MMUReadPTE[31:10]; + + // Assign outputs to ahblite + // *** Currently truncate address to 32 bits. This must be changed if + // we support larger physical address spaces + assign MMUPAdr = TranslationPAdr[31:0]; + end else begin - // sv39 not yet implemented assign SvMode = SATP_REGW[63]; + + logic [8:0] VPN2 = TranslationVAdr[38:30]; + logic [8:0] VPN1 = TranslationVAdr[29:21]; + logic [8:0] VPN0 = TranslationVAdr[20:12]; // *** could optimize by not passing offset? + + logic [55:0] TranslationPAdr; + logic [43:0] CurrentPPN; + + logic Dirty, Accessed, Global, User, + Executable, Writable, Readable, Valid; + logic ValidPTE, AccessAlert, GigapageMisaligned, MegapageMisaligned, + BadGigapage, BadMegapage, LeafPTE; + + typedef enum {IDLE, LEVEL2, LEVEL1, LEVEL0, LEAF, FAULT} statetype; + statetype WalkerState, NextWalkerState; + + // *** Do we need a synchronizer here for walker to talk to ahblite? + flopenl #(.TYPE(statetype)) mmureg(clk, reset, 1'b1, NextWalkerState, IDLE, WalkerState); + + always_comb begin + case (WalkerState) + IDLE: if (MMUTranslate) NextWalkerState = LEVEL1; + else NextWalkerState = IDLE; + LEVEL2: if (~MMUReady) NextWalkerState = LEVEL2; + else if (ValidPTE && ~LeafPTE) NextWalkerState = LEVEL1; + else NextWalkerState = FAULT; + LEVEL1: if (~MMUReady) NextWalkerState = LEVEL1; + // else if (~ValidPTE || (LeafPTE && BadMegapage)) + // NextWalkerState = FAULT; + // *** Leave megapage implementation for later + // else if (ValidPTE && LeafPTE) NextWalkerState = LEAF; + else if (ValidPTE && ~LeafPTE) NextWalkerState = LEVEL0; + else NextWalkerState = FAULT; + LEVEL0: if (~MMUReady) NextWalkerState = LEVEL0; + else if (ValidPTE && LeafPTE && ~AccessAlert) + NextWalkerState = LEAF; + else NextWalkerState = FAULT; + LEAF: if (MMUTranslate) NextWalkerState = LEVEL2; + else NextWalkerState = IDLE; + FAULT: if (MMUTranslate) NextWalkerState = LEVEL2; + else NextWalkerState = IDLE; + endcase + end + + // unswizzle PTE bits + assign {Dirty, Accessed, Global, User, + Executable, Writable, Readable, Valid} = MMUReadPTE[7:0]; + + // A megapage is a Level 1 leaf page. This page must have zero PPN[0]. + assign GigapageMisaligned = |(CurrentPPN[17:0]); + assign MegapageMisaligned = |(CurrentPPN[8:0]); + assign LeafPTE = Executable | Writable | Readable; + assign ValidPTE = Valid && ~(Writable && ~Readable); + assign AccessAlert = ~Accessed || (MemWriteM && ~Dirty); + assign BadGigapage = GigapageMisaligned || AccessAlert; // *** Implement better access/dirty scheme + assign BadMegapage = MegapageMisaligned || AccessAlert; // *** Implement better access/dirty scheme + + // *** Should translate this flop block into our flop module notation + always_ff @(posedge clk, negedge reset) + if (reset) begin + TranslationPAdr <= '0; + PageTableEntryF <= '0; + MMUTranslationComplete <= '0; + DTLBWriteM <= '0; + ITLBWriteF <= '0; + InstrPageFaultM <= '0; + LoadPageFaultM <= '0; + StorePageFaultM <= '0; + end else begin + // default values + TranslationPAdr <= '0; + PageTableEntryF <= '0; + MMUTranslationComplete <= '0; + DTLBWriteM <= '0; + ITLBWriteF <= '0; + InstrPageFaultM <= '0; + LoadPageFaultM <= '0; + StorePageFaultM <= '0; + case (NextWalkerState) + LEVEL2: begin + TranslationPAdr <= {BasePageTablePPN, VPN2, 3'b00}; + end + LEVEL1: begin + TranslationPAdr <= {CurrentPPN, VPN1, 3'b00}; + end + LEVEL0: begin + TranslationPAdr <= {CurrentPPN, VPN0, 3'b00}; + end + LEAF: begin + PageTableEntryF <= MMUReadPTE; + PageTableEntryM <= MMUReadPTE; + MMUTranslationComplete <= '1; + DTLBWriteM <= DTLBMissM; + ITLBWriteF <= ~DTLBMissM; // Prefer data over instructions + end + FAULT: begin + InstrPageFaultM <= ~DTLBMissM; + LoadPageFaultM <= DTLBMissM && ~MemWriteM; + StorePageFaultM <= DTLBMissM && MemWriteM; + end + endcase + end + + // Interpret inputs from ahblite + assign CurrentPPN = MMUReadPTE[53:10]; + + // Assign outputs to ahblite + // *** Currently truncate address to 32 bits. This must be changed if + // we support larger physical address spaces + assign MMUPAdr = TranslationPAdr[31:0]; end endgenerate - // rv32 case - - -*/ - endmodule \ No newline at end of file diff --git a/wally-pipelined/src/privileged/privileged.sv b/wally-pipelined/src/privileged/privileged.sv index c967d2629..16a3d5db0 100644 --- a/wally-pipelined/src/privileged/privileged.sv +++ b/wally-pipelined/src/privileged/privileged.sv @@ -39,6 +39,7 @@ module privileged ( input logic InstrValidW, FloatRegWriteW, LoadStallD, BPPredWrongM, input logic [3:0] InstrClassM, input logic PrivilegedM, + input logic InstrPageFaultM, LoadPageFaultM, StorePageFaultM, input logic InstrMisalignedFaultM, InstrAccessFaultF, IllegalIEUInstrFaultD, input logic LoadMisalignedFaultM, LoadAccessFaultM, input logic StoreMisalignedFaultM, StoreAccessFaultM, @@ -48,7 +49,7 @@ module privileged ( output logic [1:0] PrivilegeModeW, output logic [`XLEN-1:0] SATP_REGW, output logic [2:0] FRM_REGW, - input logic FlushD, FlushE, FlushM, StallD, StallW + input logic FlushD, FlushE, FlushM, StallD, StallW, StallE, StallM ); logic [1:0] NextPrivilegeModeM; @@ -65,7 +66,6 @@ module privileged ( logic IllegalInstrFaultM; logic BreakpointFaultM, EcallFaultM; - logic InstrPageFaultM, LoadPageFaultM, StorePageFaultM; logic MTrapM, STrapM, UTrapM; logic [1:0] STATUS_MPP; @@ -119,9 +119,11 @@ module privileged ( assign BreakpointFaultM = ebreakM; // could have other causes too assign EcallFaultM = ecallM; - assign InstrPageFaultM = 0; - assign LoadPageFaultM = 0; - assign StorePageFaultM = 0; + // *** Page faults now driven by page table walker. Might need to make the + // below signals ORs of a walker fault and a tlb fault if both of those come in + // assign InstrPageFaultM = 0; + // assign LoadPageFaultM = 0; + // assign StorePageFaultM = 0; // pipeline fault signals flopenrc #(1) faultregD(clk, reset, FlushD, ~StallD, InstrAccessFaultF, InstrAccessFaultD); diff --git a/wally-pipelined/src/wally/wallypipelinedhart.sv b/wally-pipelined/src/wally/wallypipelinedhart.sv index 5975015ff..67ef8b204 100644 --- a/wally-pipelined/src/wally/wallypipelinedhart.sv +++ b/wally-pipelined/src/wally/wallypipelinedhart.sv @@ -76,6 +76,7 @@ module wallypipelinedhart ( logic InstrMisalignedFaultM; logic DataMisalignedM; logic IllegalBaseInstrFaultD, IllegalIEUInstrFaultD; + logic InstrPageFaultM, LoadPageFaultM, StorePageFaultM; logic LoadMisalignedFaultM, LoadAccessFaultM; logic StoreMisalignedFaultM, StoreAccessFaultM; logic [`XLEN-1:0] InstrMisalignedAdrM; @@ -98,7 +99,7 @@ module wallypipelinedhart ( logic [`XLEN-1:0] PageTableEntryF, PageTableEntryM; logic [`XLEN-1:0] MMUPAdr, MMUReadPTE; - logic MMUTranslate, MMUReady; + logic MMUTranslate, MMUTranslationComplete, MMUReady; // bus interface to dmem logic MemReadM, MemWriteM;