diff --git a/pipelined/regression/Makefile b/pipelined/regression/Makefile index 62ef4a4ea..b323bdb97 100644 --- a/pipelined/regression/Makefile +++ b/pipelined/regression/Makefile @@ -3,11 +3,14 @@ make all: make -C ../../addins/riscv-arch-test make -C ../../addins/riscv-arch-test XLEN=32 exe2memfile.pl ../../addins/riscv-arch-test/work/*/*/*.elf + # extractFunctionRadix. *** # Build wally-riscv-arch-test make -C ../../tests/wally-riscv-arch-test/ make -C ../../tests/wally-riscv-arch-test/ XLEN=32 exe2memfile.pl ../../tests/wally-riscv-arch-test/work/*/*/*.elf + # ***extractFunctionRadix + # *** use elf2hex # *** add optional imperas tests diff --git a/pipelined/regression/sim-wally-batch b/pipelined/regression/sim-wally-batch index 73ad1d838..014b36c74 100755 --- a/pipelined/regression/sim-wally-batch +++ b/pipelined/regression/sim-wally-batch @@ -1,3 +1,3 @@ vsim -c < 32) + if (instr16[6:5] == 2'b00) + InstrD = {7'b0100000, rs2p, rds1p, 3'b000, rds1p, 7'b0111011}; // c.subw + else if (instr16[6:5] == 2'b01) + InstrD = {7'b0000000, rs2p, rds1p, 3'b000, rds1p, 7'b0111011}; // c.addw + else begin // reserved IllegalCompInstrD = 1; InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap end - 5'b00001: InstrD = {immCLD, rs1p, 3'b011, rdp, 7'b0000111}; // c.fld - 5'b00010: InstrD = {immCL, rs1p, 3'b010, rdp, 7'b0000011}; // c.lw - 5'b00011: if (`XLEN==32) - InstrD = {immCL, rs1p, 3'b010, rdp, 7'b0000111}; // c.flw + else begin // illegal instruction + IllegalCompInstrD = 1; + InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap + end + 5'b01101: InstrD = {immCJ, 5'b00000, 7'b1101111}; // c.j + 5'b01110: InstrD = {immCB[11:5], 5'b00000, rs1p, 3'b000, immCB[4:0], 7'b1100011}; // c.beqz + 5'b01111: InstrD = {immCB[11:5], 5'b00000, rs1p, 3'b001, immCB[4:0], 7'b1100011}; // c.bnez + 5'b10000: InstrD = {6'b000000, immSH, rds1, 3'b001, rds1, 7'b0010011}; // c.slli + 5'b10001: InstrD = {immCILSPD, 5'b00010, 3'b011, rds1, 7'b0000111}; // c.fldsp + 5'b10010: InstrD = {immCILSP, 5'b00010, 3'b010, rds1, 7'b0000011}; // c.lwsp + 5'b10011: if (`XLEN == 32) + InstrD = {immCILSP, 5'b00010, 3'b010, rds1, 7'b0000111}; // c.flwsp + else + InstrD = {immCILSPD, 5'b00010, 3'b011, rds1, 7'b0000011}; // c.ldsp + 5'b10100: if (instr16[12] == 0) + if (instr16[6:2] == 5'b00000) + InstrD = {7'b0000000, 5'b00000, rds1, 3'b000, 5'b00000, 7'b1100111}; // c.jr else - InstrD = {immCLD, rs1p, 3'b011, rdp, 7'b0000011}; // c.ld; - 5'b00101: InstrD = {immCSD[11:5], rs2p, rs1p, 3'b011, immCSD[4:0], 7'b0100111}; // c.fsd - 5'b00110: InstrD = {immCS[11:5], rs2p, rs1p, 3'b010, immCS[4:0], 7'b0100011}; // c.sw - 5'b00111: if (`XLEN==32) - InstrD = {immCS[11:5], rs2p, rs1p, 3'b010, immCS[4:0], 7'b0100111}; // c.fsw - else - InstrD = {immCSD[11:5], rs2p, rs1p, 3'b011, immCSD[4:0], 7'b0100011}; //c.sd - 5'b01000: InstrD = {immCI, rds1, 3'b000, rds1, 7'b0010011}; // c.addi - 5'b01001: if (`XLEN==32) - InstrD = {immCJ, 5'b00001, 7'b1101111}; // c.jal - else - InstrD = {immCI, rds1, 3'b000, rds1, 7'b0011011}; // c.addiw - 5'b01010: InstrD = {immCI, 5'b00000, 3'b000, rds1, 7'b0010011}; // c.li - 5'b01011: if (rds1 != 5'b00010) - InstrD = {immCILUI, rds1, 7'b0110111}; // c.lui - else - InstrD = {immCIASP, rds1, 3'b000, rds1, 7'b0010011}; // c.addi16sp - 5'b01100: if (instr16[11:10] == 2'b00) - InstrD = {6'b000000, immSH, rds1p, 3'b101, rds1p, 7'b0010011}; // c.srli - else if (instr16[11:10] == 2'b01) - InstrD = {6'b010000, immSH, rds1p, 3'b101, rds1p, 7'b0010011}; // c.srai - else if (instr16[11:10] == 2'b10) - InstrD = {immCI, rds1p, 3'b111, rds1p, 7'b0010011}; // c.andi - else if (instr16[12:10] == 3'b011) - if (instr16[6:5] == 2'b00) - InstrD = {7'b0100000, rs2p, rds1p, 3'b000, rds1p, 7'b0110011}; // c.sub - else if (instr16[6:5] == 2'b01) - InstrD = {7'b0000000, rs2p, rds1p, 3'b100, rds1p, 7'b0110011}; // c.xor - else if (instr16[6:5] == 2'b10) - InstrD = {7'b0000000, rs2p, rds1p, 3'b110, rds1p, 7'b0110011}; // c.or - else // if (instr16[6:5] == 2'b11) - InstrD = {7'b0000000, rs2p, rds1p, 3'b111, rds1p, 7'b0110011}; // c.and - else if (instr16[12:10] == 3'b111 & `XLEN > 32) - if (instr16[6:5] == 2'b00) - InstrD = {7'b0100000, rs2p, rds1p, 3'b000, rds1p, 7'b0111011}; // c.subw - else if (instr16[6:5] == 2'b01) - InstrD = {7'b0000000, rs2p, rds1p, 3'b000, rds1p, 7'b0111011}; // c.addw - else begin // reserved - IllegalCompInstrD = 1; - InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap - end - else begin // illegal instruction - IllegalCompInstrD = 1; - InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap - end - 5'b01101: InstrD = {immCJ, 5'b00000, 7'b1101111}; // c.j - 5'b01110: InstrD = {immCB[11:5], 5'b00000, rs1p, 3'b000, immCB[4:0], 7'b1100011}; // c.beqz - 5'b01111: InstrD = {immCB[11:5], 5'b00000, rs1p, 3'b001, immCB[4:0], 7'b1100011}; // c.bnez - 5'b10000: InstrD = {6'b000000, immSH, rds1, 3'b001, rds1, 7'b0010011}; // c.slli - 5'b10001: InstrD = {immCILSPD, 5'b00010, 3'b011, rds1, 7'b0000111}; // c.fldsp - 5'b10010: InstrD = {immCILSP, 5'b00010, 3'b010, rds1, 7'b0000011}; // c.lwsp - 5'b10011: if (`XLEN == 32) - InstrD = {immCILSP, 5'b00010, 3'b010, rds1, 7'b0000111}; // c.flwsp - else - InstrD = {immCILSPD, 5'b00010, 3'b011, rds1, 7'b0000011}; // c.ldsp - 5'b10100: if (instr16[12] == 0) - if (instr16[6:2] == 5'b00000) - InstrD = {7'b0000000, 5'b00000, rds1, 3'b000, 5'b00000, 7'b1100111}; // c.jr + InstrD = {7'b0000000, rs2, 5'b00000, 3'b000, rds1, 7'b0110011}; // c.mv + else + if (rs2 == 5'b00000) + if (rds1 == 5'b00000) + InstrD = {12'b1, 5'b00000, 3'b000, 5'b00000, 7'b1110011}; // c.ebreak else - InstrD = {7'b0000000, rs2, 5'b00000, 3'b000, rds1, 7'b0110011}; // c.mv + InstrD = {12'b0, rds1, 3'b000, 5'b00001, 7'b1100111}; // c.jalr else - if (rs2 == 5'b00000) - if (rds1 == 5'b00000) - InstrD = {12'b1, 5'b00000, 3'b000, 5'b00000, 7'b1110011}; // c.ebreak - else - InstrD = {12'b0, rds1, 3'b000, 5'b00001, 7'b1100111}; // c.jalr - else - InstrD = {7'b0000000, rs2, rds1, 3'b000, rds1, 7'b0110011}; // c.add - 5'b10101: InstrD = {immCSSD[11:5], rs2, 5'b00010, 3'b011, immCSSD[4:0], 7'b0100111}; // c.fsdsp - 5'b10110: InstrD = {immCSS[11:5], rs2, 5'b00010, 3'b010, immCSS[4:0], 7'b0100011}; // c.swsp - 5'b10111: if (`XLEN==32) - InstrD = {immCSS[11:5], rs2, 5'b00010, 3'b010, immCSS[4:0], 7'b0100111}; // c.fswsp - else - InstrD = {immCSSD[11:5], rs2, 5'b00010, 3'b011, immCSSD[4:0], 7'b0100011}; // c.sdsp - default: begin // illegal instruction - IllegalCompInstrD = 1; - InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap - end - endcase - end - end - endgenerate + InstrD = {7'b0000000, rs2, rds1, 3'b000, rds1, 7'b0110011}; // c.add + 5'b10101: InstrD = {immCSSD[11:5], rs2, 5'b00010, 3'b011, immCSSD[4:0], 7'b0100111}; // c.fsdsp + 5'b10110: InstrD = {immCSS[11:5], rs2, 5'b00010, 3'b010, immCSS[4:0], 7'b0100011}; // c.swsp + 5'b10111: if (`XLEN==32) + InstrD = {immCSS[11:5], rs2, 5'b00010, 3'b010, immCSS[4:0], 7'b0100111}; // c.fswsp + else + InstrD = {immCSSD[11:5], rs2, 5'b00010, 3'b011, immCSSD[4:0], 7'b0100011}; // c.sdsp + default: begin // illegal instruction + IllegalCompInstrD = 1; + InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap + end + endcase + end + end endmodule diff --git a/pipelined/src/lsu/subwordread.sv b/pipelined/src/lsu/subwordread.sv index 8d787cdd3..1e0f380c6 100644 --- a/pipelined/src/lsu/subwordread.sv +++ b/pipelined/src/lsu/subwordread.sv @@ -38,77 +38,75 @@ module subwordread // Funct3M[2] is the unsigned bit. mask upper bits. // Funct3M[1:0] is the size of the memory access. - generate - if (`XLEN == 64) begin:swrmux - // ByteMe mux - always_comb - case(LsuPAdrM[2:0]) - 3'b000: ByteM = ReadDataWordMuxM[7:0]; - 3'b001: ByteM = ReadDataWordMuxM[15:8]; - 3'b010: ByteM = ReadDataWordMuxM[23:16]; - 3'b011: ByteM = ReadDataWordMuxM[31:24]; - 3'b100: ByteM = ReadDataWordMuxM[39:32]; - 3'b101: ByteM = ReadDataWordMuxM[47:40]; - 3'b110: ByteM = ReadDataWordMuxM[55:48]; - 3'b111: ByteM = ReadDataWordMuxM[63:56]; - endcase + if (`XLEN == 64) begin:swrmux + // ByteMe mux + always_comb + case(LsuPAdrM[2:0]) + 3'b000: ByteM = ReadDataWordMuxM[7:0]; + 3'b001: ByteM = ReadDataWordMuxM[15:8]; + 3'b010: ByteM = ReadDataWordMuxM[23:16]; + 3'b011: ByteM = ReadDataWordMuxM[31:24]; + 3'b100: ByteM = ReadDataWordMuxM[39:32]; + 3'b101: ByteM = ReadDataWordMuxM[47:40]; + 3'b110: ByteM = ReadDataWordMuxM[55:48]; + 3'b111: ByteM = ReadDataWordMuxM[63:56]; + endcase + + // halfword mux + always_comb + case(LsuPAdrM[2:1]) + 2'b00: HalfwordM = ReadDataWordMuxM[15:0]; + 2'b01: HalfwordM = ReadDataWordMuxM[31:16]; + 2'b10: HalfwordM = ReadDataWordMuxM[47:32]; + 2'b11: HalfwordM = ReadDataWordMuxM[63:48]; + endcase - // halfword mux - always_comb - case(LsuPAdrM[2:1]) - 2'b00: HalfwordM = ReadDataWordMuxM[15:0]; - 2'b01: HalfwordM = ReadDataWordMuxM[31:16]; - 2'b10: HalfwordM = ReadDataWordMuxM[47:32]; - 2'b11: HalfwordM = ReadDataWordMuxM[63:48]; - endcase - - logic [31:0] WordM; - - always_comb - case(LsuPAdrM[2]) - 1'b0: WordM = ReadDataWordMuxM[31:0]; - 1'b1: WordM = ReadDataWordMuxM[63:32]; - endcase - - // sign extension - always_comb - case(Funct3M) - 3'b000: ReadDataM = {{56{ByteM[7]}}, ByteM}; // lb - 3'b001: ReadDataM = {{48{HalfwordM[15]}}, HalfwordM[15:0]}; // lh - 3'b010: ReadDataM = {{32{WordM[31]}}, WordM[31:0]}; // lw - 3'b011: ReadDataM = ReadDataWordMuxM; // ld - 3'b100: ReadDataM = {56'b0, ByteM[7:0]}; // lbu - 3'b101: ReadDataM = {48'b0, HalfwordM[15:0]}; // lhu - 3'b110: ReadDataM = {32'b0, WordM[31:0]}; // lwu - default: ReadDataM = ReadDataWordMuxM; // Shouldn't happen - endcase - end else begin :swrmux // 32-bit - // byte mux - always_comb - case(LsuPAdrM[1:0]) - 2'b00: ByteM = ReadDataWordMuxM[7:0]; - 2'b01: ByteM = ReadDataWordMuxM[15:8]; - 2'b10: ByteM = ReadDataWordMuxM[23:16]; - 2'b11: ByteM = ReadDataWordMuxM[31:24]; - endcase + logic [31:0] WordM; - // halfword mux - always_comb - case(LsuPAdrM[1]) - 1'b0: HalfwordM = ReadDataWordMuxM[15:0]; - 1'b1: HalfwordM = ReadDataWordMuxM[31:16]; + always_comb + case(LsuPAdrM[2]) + 1'b0: WordM = ReadDataWordMuxM[31:0]; + 1'b1: WordM = ReadDataWordMuxM[63:32]; endcase - // sign extension - always_comb - case(Funct3M) - 3'b000: ReadDataM = {{24{ByteM[7]}}, ByteM}; // lb - 3'b001: ReadDataM = {{16{HalfwordM[15]}}, HalfwordM[15:0]}; // lh - 3'b010: ReadDataM = ReadDataWordMuxM; // lw - 3'b100: ReadDataM = {24'b0, ByteM[7:0]}; // lbu - 3'b101: ReadDataM = {16'b0, HalfwordM[15:0]}; // lhu - default: ReadDataM = ReadDataWordMuxM; - endcase - end - endgenerate + // sign extension + always_comb + case(Funct3M) + 3'b000: ReadDataM = {{56{ByteM[7]}}, ByteM}; // lb + 3'b001: ReadDataM = {{48{HalfwordM[15]}}, HalfwordM[15:0]}; // lh + 3'b010: ReadDataM = {{32{WordM[31]}}, WordM[31:0]}; // lw + 3'b011: ReadDataM = ReadDataWordMuxM; // ld + 3'b100: ReadDataM = {56'b0, ByteM[7:0]}; // lbu + 3'b101: ReadDataM = {48'b0, HalfwordM[15:0]}; // lhu + 3'b110: ReadDataM = {32'b0, WordM[31:0]}; // lwu + default: ReadDataM = ReadDataWordMuxM; // Shouldn't happen + endcase + end else begin:swrmux // 32-bit + // byte mux + always_comb + case(LsuPAdrM[1:0]) + 2'b00: ByteM = ReadDataWordMuxM[7:0]; + 2'b01: ByteM = ReadDataWordMuxM[15:8]; + 2'b10: ByteM = ReadDataWordMuxM[23:16]; + 2'b11: ByteM = ReadDataWordMuxM[31:24]; + endcase + + // halfword mux + always_comb + case(LsuPAdrM[1]) + 1'b0: HalfwordM = ReadDataWordMuxM[15:0]; + 1'b1: HalfwordM = ReadDataWordMuxM[31:16]; + endcase + + // sign extension + always_comb + case(Funct3M) + 3'b000: ReadDataM = {{24{ByteM[7]}}, ByteM}; // lb + 3'b001: ReadDataM = {{16{HalfwordM[15]}}, HalfwordM[15:0]}; // lh + 3'b010: ReadDataM = ReadDataWordMuxM; // lw + 3'b100: ReadDataM = {24'b0, ByteM[7:0]}; // lbu + 3'b101: ReadDataM = {16'b0, HalfwordM[15:0]}; // lhu + default: ReadDataM = ReadDataWordMuxM; + endcase + end endmodule diff --git a/pipelined/src/mmu/hptw.sv b/pipelined/src/mmu/hptw.sv index 95d202679..157a80bcb 100644 --- a/pipelined/src/mmu/hptw.sv +++ b/pipelined/src/mmu/hptw.sv @@ -52,7 +52,7 @@ module hptw L1_ADR, L1_RD, L2_ADR, L2_RD, L3_ADR, L3_RD, - LEAF, IDLE} statetype; // *** placed outside generate statement to remove synthesis errors + LEAF, IDLE} statetype; logic DTLBWalk; // register TLBs translation miss requests logic [`PPN_BITS-1:0] BasePageTablePPN; diff --git a/pipelined/src/mmu/mmu.sv b/pipelined/src/mmu/mmu.sv index 43251b7a4..e69028118 100644 --- a/pipelined/src/mmu/mmu.sv +++ b/pipelined/src/mmu/mmu.sv @@ -90,27 +90,25 @@ module mmu #(parameter TLB_ENTRIES = 8, // number of TLB Entries // only instantiate TLB if Virtual Memory is supported - generate - if (`MEM_VIRTMEM) begin:tlb - logic ReadAccess, WriteAccess; - assign ReadAccess = ExecuteAccessF | ReadAccessM; // execute also acts as a TLB read. Execute and Read are never active for the same MMU, so safe to mix pipestages - assign WriteAccess = WriteAccessM; - tlb #(.TLB_ENTRIES(TLB_ENTRIES), .ITLB(IMMU)) - tlb(.clk, .reset, - .SATP_MODE(SATP_REGW[`XLEN-1:`XLEN-`SVMODE_BITS]), - .SATP_ASID(SATP_REGW[`ASID_BASE+`ASID_BITS-1:`ASID_BASE]), - .VAdr, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, - .PrivilegeModeW, .ReadAccess, .WriteAccess, - .DisableTranslation, .PTE, .PageTypeWriteVal, - .TLBWrite, .TLBFlush, .TLBPAdr, .TLBMiss, .TLBHit, - .Translate, .TLBPageFault); - end else begin:tlb// just pass address through as physical - assign Translate = 0; - assign TLBMiss = 0; - assign TLBHit = 1; // *** is this necessary - assign TLBPageFault = 0; - end - endgenerate + if (`MEM_VIRTMEM) begin:tlb + logic ReadAccess, WriteAccess; + assign ReadAccess = ExecuteAccessF | ReadAccessM; // execute also acts as a TLB read. Execute and Read are never active for the same MMU, so safe to mix pipestages + assign WriteAccess = WriteAccessM; + tlb #(.TLB_ENTRIES(TLB_ENTRIES), .ITLB(IMMU)) + tlb(.clk, .reset, + .SATP_MODE(SATP_REGW[`XLEN-1:`XLEN-`SVMODE_BITS]), + .SATP_ASID(SATP_REGW[`ASID_BASE+`ASID_BITS-1:`ASID_BASE]), + .VAdr, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, + .PrivilegeModeW, .ReadAccess, .WriteAccess, + .DisableTranslation, .PTE, .PageTypeWriteVal, + .TLBWrite, .TLBFlush, .TLBPAdr, .TLBMiss, .TLBHit, + .Translate, .TLBPageFault); + end else begin:tlb// just pass address through as physical + assign Translate = 0; + assign TLBMiss = 0; + assign TLBHit = 1; // *** is this necessary + assign TLBPageFault = 0; + end // If translation is occuring, select translated physical address from TLB mux2 #(`PA_BITS) addressmux(PAdr, TLBPAdr, Translate, PhysicalAddress); diff --git a/pipelined/src/mmu/pmpadrdec.sv b/pipelined/src/mmu/pmpadrdec.sv index 868688863..4913f088c 100644 --- a/pipelined/src/mmu/pmpadrdec.sv +++ b/pipelined/src/mmu/pmpadrdec.sv @@ -68,7 +68,7 @@ module pmpadrdec ( assign NAMask[1:0] = {2'b11}; assign NAMask[`PA_BITS-1:2] = (PMPAdr[`PA_BITS-3:0] + {{(`PA_BITS-3){1'b0}}, (AdrMode == NAPOT)}) ^ PMPAdr[`PA_BITS-3:0]; - // generates a mask where the bottom k bits are 1, corresponding to a size of 2^k bytes for this memory region. + // form a mask where the bottom k bits are 1, corresponding to a size of 2^k bytes for this memory region. // This assumes we're using at least an NA4 region, but works for any size NAPOT region. assign NABase = {(PMPAdr[`PA_BITS-3:0] & ~NAMask[`PA_BITS-1:2]), 2'b00}; // base physical address of the pmp. diff --git a/pipelined/src/mmu/pmpchecker.sv b/pipelined/src/mmu/pmpchecker.sv index 824217f09..593b2c19a 100644 --- a/pipelined/src/mmu/pmpchecker.sv +++ b/pipelined/src/mmu/pmpchecker.sv @@ -47,37 +47,34 @@ module pmpchecker ( output logic PMPStoreAccessFaultM ); - generate - if (`PMP_ENTRIES > 0) begin: pmpchecker - // Bit i is high when the address falls in PMP region i - logic EnforcePMP; - logic [`PMP_ENTRIES-1:0] Match; // physical address matches one of the pmp ranges - logic [`PMP_ENTRIES-1:0] FirstMatch; // onehot encoding for the first pmpaddr to match the current address. - logic [`PMP_ENTRIES-1:0] Active; // PMP register i is non-null - logic [`PMP_ENTRIES-1:0] L, X, W, R; // PMP matches and has flag set - logic [`PMP_ENTRIES-1:0] PAgePMPAdr; // for TOR PMP matching, PhysicalAddress > PMPAdr[i] - - pmpadrdec pmpadrdecs[`PMP_ENTRIES-1:0]( - .PhysicalAddress, - .PMPCfg(PMPCFG_ARRAY_REGW), - .PMPAdr(PMPADDR_ARRAY_REGW), - .PAgePMPAdrIn({PAgePMPAdr[`PMP_ENTRIES-2:0], 1'b1}), - .PAgePMPAdrOut(PAgePMPAdr), - .FirstMatch, .Match, .Active, .L, .X, .W, .R); + if (`PMP_ENTRIES > 0) begin: pmpchecker + // Bit i is high when the address falls in PMP region i + logic EnforcePMP; + logic [`PMP_ENTRIES-1:0] Match; // physical address matches one of the pmp ranges + logic [`PMP_ENTRIES-1:0] FirstMatch; // onehot encoding for the first pmpaddr to match the current address. + logic [`PMP_ENTRIES-1:0] Active; // PMP register i is non-null + logic [`PMP_ENTRIES-1:0] L, X, W, R; // PMP matches and has flag set + logic [`PMP_ENTRIES-1:0] PAgePMPAdr; // for TOR PMP matching, PhysicalAddress > PMPAdr[i] - priorityonehot #(`PMP_ENTRIES) pmppriority(.a(Match), .y(FirstMatch)); // combine the match signal from all the adress decoders to find the first one that matches. + pmpadrdec pmpadrdecs[`PMP_ENTRIES-1:0]( + .PhysicalAddress, + .PMPCfg(PMPCFG_ARRAY_REGW), + .PMPAdr(PMPADDR_ARRAY_REGW), + .PAgePMPAdrIn({PAgePMPAdr[`PMP_ENTRIES-2:0], 1'b1}), + .PAgePMPAdrOut(PAgePMPAdr), + .FirstMatch, .Match, .Active, .L, .X, .W, .R); - // Only enforce PMP checking for S and U modes when at least one PMP is active or in Machine mode when L bit is set in selected region - assign EnforcePMP = (PrivilegeModeW == `M_MODE) ? |L : |Active; + priorityonehot #(`PMP_ENTRIES) pmppriority(.a(Match), .y(FirstMatch)); // combine the match signal from all the adress decoders to find the first one that matches. - assign PMPInstrAccessFaultF = EnforcePMP & ExecuteAccessF & ~|X; - assign PMPStoreAccessFaultM = EnforcePMP & WriteAccessM & ~|W; - assign PMPLoadAccessFaultM = EnforcePMP & ReadAccessM & ~|R; - end else begin: pmpchecker // no checker - assign PMPInstrAccessFaultF = 0; - assign PMPLoadAccessFaultM = 0; - assign PMPStoreAccessFaultM = 0; - end - endgenerate - //assign PMPSquashBusAccess = PMPInstrAccessFaultF | PMPLoadAccessFaultM | PMPStoreAccessFaultM; + // Only enforce PMP checking for S and U modes when at least one PMP is active or in Machine mode when L bit is set in selected region + assign EnforcePMP = (PrivilegeModeW == `M_MODE) ? |L : |Active; + + assign PMPInstrAccessFaultF = EnforcePMP & ExecuteAccessF & ~|X; + assign PMPStoreAccessFaultM = EnforcePMP & WriteAccessM & ~|W; + assign PMPLoadAccessFaultM = EnforcePMP & ReadAccessM & ~|R; + end else begin: pmpchecker // no checker + assign PMPInstrAccessFaultF = 0; + assign PMPLoadAccessFaultM = 0; + assign PMPStoreAccessFaultM = 0; + end endmodule diff --git a/pipelined/src/mmu/priorityonehot.sv b/pipelined/src/mmu/priorityonehot.sv index 849f178ee..e6e8ec225 100644 --- a/pipelined/src/mmu/priorityonehot.sv +++ b/pipelined/src/mmu/priorityonehot.sv @@ -34,25 +34,9 @@ module priorityonehot #(parameter ENTRIES = 8) ( input logic [ENTRIES-1:0] a, output logic [ENTRIES-1:0] y ); - - /* verilator lint_off UNOPTFLAT */ - logic [ENTRIES-1:0] nolower; - // generate thermometer code mask + // create thermometer code mask prioritythermometer #(ENTRIES) maskgen(.a({a[ENTRIES-2:0], 1'b1}), .y(nolower)); - // genvar i; - // generate - // assign nolower[0] = 1'b1; - // for (i=1; i 2'd0); // least signifcant section - assign Match1 = (Query1 == Key1) | (PageType > 2'd1); - assign Match2 = (Query2 == Key2) | (PageType > 2'd2); - assign Match3 = (Query3 == Key3) | SV39Mode; // this should always match in sv39 because they aren't used - - assign Match = Match0 & Match1 & Match2 & Match3 & MatchASID & Valid; - end - endgenerate + // Calculate the actual match value based on the input vpn and the page type. + // For example, a gigapage in SV39 only cares about VPN[2], so VPN[0] and VPN[1] + // should automatically match. + assign Match0 = (Query0 == Key0) | (PageType > 2'd0); // least signifcant section + assign Match1 = (Query1 == Key1) | (PageType > 2'd1); + assign Match2 = (Query2 == Key2) | (PageType > 2'd2); + assign Match3 = (Query3 == Key3) | SV39Mode; // this should always match in sv39 because they aren't used + + assign Match = Match0 & Match1 & Match2 & Match3 & MatchASID & Valid; + end // On a write, update the type of the page referred to by this line. flopenr #(2) pagetypeflop(clk, reset, WriteEnable, PageTypeWriteVal, PageType); diff --git a/pipelined/src/mmu/tlbcontrol.sv b/pipelined/src/mmu/tlbcontrol.sv index f3844717f..cb6675cfd 100644 --- a/pipelined/src/mmu/tlbcontrol.sv +++ b/pipelined/src/mmu/tlbcontrol.sv @@ -60,65 +60,59 @@ module tlbcontrol #(parameter ITLB = 0) ( logic UpperBitsUnequalPageFault; logic DAPageFault; logic TLBAccess; + logic ImproperPrivilege; // Grab the sv mode from SATP and determine whether translation should occur assign EffectivePrivilegeMode = (ITLB == 1) ? PrivilegeModeW : (STATUS_MPRV ? STATUS_MPP : PrivilegeModeW); // DTLB uses MPP mode when MPRV is 1 assign Translate = (SATP_MODE != `NO_TRANSLATE) & (EffectivePrivilegeMode != `M_MODE) & ~DisableTranslation; - generate - if (`XLEN==64) begin:rv64 - assign SV39Mode = (SATP_MODE == `SV39); - // generate page fault if upper bits aren't all the same - logic UpperEqual39, UpperEqual48; - assign UpperEqual39 = &(VAdr[63:38]) | ~|(VAdr[63:38]); - assign UpperEqual48 = &(VAdr[63:47]) | ~|(VAdr[63:47]); - assign UpperBitsUnequalPageFault = SV39Mode ? ~UpperEqual39 : ~UpperEqual48; - end else begin - assign SV39Mode = 0; - assign UpperBitsUnequalPageFault = 0; - end - endgenerate + if (`XLEN==64) begin:rv64 + assign SV39Mode = (SATP_MODE == `SV39); + // page fault if upper bits aren't all the same + logic UpperEqual39, UpperEqual48; + assign UpperEqual39 = &(VAdr[63:38]) | ~|(VAdr[63:38]); + assign UpperEqual48 = &(VAdr[63:47]) | ~|(VAdr[63:47]); + assign UpperBitsUnequalPageFault = SV39Mode ? ~UpperEqual39 : ~UpperEqual48; + end else begin + assign SV39Mode = 0; + assign UpperBitsUnequalPageFault = 0; + end // Determine whether TLB is being used assign TLBAccess = ReadAccess | WriteAccess; // Check whether upper bits of virtual addresss are all equal - // unswizzle useful PTE bits assign {PTE_D, PTE_A} = PTEAccessBits[7:6]; assign {PTE_U, PTE_X, PTE_W, PTE_R, PTE_V} = PTEAccessBits[4:0]; // Check whether the access is allowed, page faulting if not. - generate - if (ITLB == 1) begin:itlb // Instruction TLB fault checking - logic ImproperPrivilege; + if (ITLB == 1) begin:itlb // Instruction TLB fault checking + // User mode may only execute user mode pages, and supervisor mode may + // only execute non-user mode pages. + assign ImproperPrivilege = ((EffectivePrivilegeMode == `U_MODE) & ~PTE_U) | + ((EffectivePrivilegeMode == `S_MODE) & PTE_U); + // fault for software handling if access bit is off + assign DAPageFault = ~PTE_A; + assign TLBPageFault = (Translate & TLBHit & (ImproperPrivilege | ~PTE_X | DAPageFault | UpperBitsUnequalPageFault | Misaligned | ~PTE_V)); + end else begin:dtlb // Data TLB fault checking + logic InvalidRead, InvalidWrite; - // User mode may only execute user mode pages, and supervisor mode may - // only execute non-user mode pages. - assign ImproperPrivilege = ((EffectivePrivilegeMode == `U_MODE) & ~PTE_U) | - ((EffectivePrivilegeMode == `S_MODE) & PTE_U); - // fault for software handling if access bit is off - assign DAPageFault = ~PTE_A; - assign TLBPageFault = (Translate & TLBHit & (ImproperPrivilege | ~PTE_X | DAPageFault | UpperBitsUnequalPageFault | Misaligned | ~PTE_V)); - end else begin:dtlb // Data TLB fault checking - logic ImproperPrivilege, InvalidRead, InvalidWrite; - - // User mode may only load/store from user mode pages, and supervisor mode - // may only access user mode pages when STATUS_SUM is low. - assign ImproperPrivilege = ((EffectivePrivilegeMode == `U_MODE) & ~PTE_U) | - ((EffectivePrivilegeMode == `S_MODE) & PTE_U & ~STATUS_SUM); - // Check for read error. Reads are invalid when the page is not readable - // (and executable pages are not readable) or when the page is neither - // readable nor executable (and executable pages are readable). - assign InvalidRead = ReadAccess & ~PTE_R & (~STATUS_MXR | ~PTE_X); - // Check for write error. Writes are invalid when the page's write bit is - // low. - assign InvalidWrite = WriteAccess & ~PTE_W; - // Fault for software handling if access bit is off or writing a page with dirty bit off - assign DAPageFault = ~PTE_A | WriteAccess & ~PTE_D; - assign TLBPageFault = (Translate & TLBHit & (ImproperPrivilege | InvalidRead | InvalidWrite | DAPageFault | UpperBitsUnequalPageFault | Misaligned | ~PTE_V)); - end - endgenerate + // User mode may only load/store from user mode pages, and supervisor mode + // may only access user mode pages when STATUS_SUM is low. + assign ImproperPrivilege = ((EffectivePrivilegeMode == `U_MODE) & ~PTE_U) | + ((EffectivePrivilegeMode == `S_MODE) & PTE_U & ~STATUS_SUM); + // Check for read error. Reads are invalid when the page is not readable + // (and executable pages are not readable) or when the page is neither + // readable nor executable (and executable pages are readable). + assign InvalidRead = ReadAccess & ~PTE_R & (~STATUS_MXR | ~PTE_X); + // Check for write error. Writes are invalid when the page's write bit is + // low. + assign InvalidWrite = WriteAccess & ~PTE_W; + // Fault for software handling if access bit is off or writing a page with dirty bit off + assign DAPageFault = ~PTE_A | WriteAccess & ~PTE_D; + assign TLBPageFault = (Translate & TLBHit & (ImproperPrivilege | InvalidRead | InvalidWrite | DAPageFault | UpperBitsUnequalPageFault | Misaligned | ~PTE_V)); + end assign TLBHit = CAMHit & TLBAccess; assign TLBMiss = (~CAMHit | TLBFlush) & Translate & TLBAccess; diff --git a/pipelined/src/mmu/tlbmixer.sv b/pipelined/src/mmu/tlbmixer.sv index 3e3a15601..f44da6a80 100644 --- a/pipelined/src/mmu/tlbmixer.sv +++ b/pipelined/src/mmu/tlbmixer.sv @@ -43,18 +43,16 @@ module tlbmixer ( logic [`PPN_BITS-1:0] PPNMixed; // produce PageNumberMask with 1s where virtual page number bits should be untranslaetd for superpages - generate - if (`XLEN == 32) - // kilopage: 22 bits of PPN, 0 bits of VPN - // megapage: 12 bits of PPN, 10 bits of VPN - mux2 #(22) pnm(22'h000000, 22'h0003FF, HitPageType[0], PageNumberMask); - else - // kilopage: 44 bits of PPN, 0 bits of VPN - // megapage: 35 bits of PPN, 9 bits of VPN - // gigapage: 26 bits of PPN, 18 bits of VPN - // terapage: 17 bits of PPN, 27 bits of VPN - mux4 #(44) pnm(44'h00000000000, 44'h000000001FF, 44'h0000003FFFF, 44'h00007FFFFFF, HitPageType, PageNumberMask); - endgenerate + if (`XLEN == 32) + // kilopage: 22 bits of PPN, 0 bits of VPN + // megapage: 12 bits of PPN, 10 bits of VPN + mux2 #(22) pnm(22'h000000, 22'h0003FF, HitPageType[0], PageNumberMask); + else + // kilopage: 44 bits of PPN, 0 bits of VPN + // megapage: 35 bits of PPN, 9 bits of VPN + // gigapage: 26 bits of PPN, 18 bits of VPN + // terapage: 17 bits of PPN, 27 bits of VPN + mux4 #(44) pnm(44'h00000000000, 44'h000000001FF, 44'h0000003FFFF, 44'h00007FFFFFF, HitPageType, PageNumberMask); // merge low segments of VPN with high segments of PPN decided by the pagetype. assign ZeroExtendedVPN = {{EXTRA_BITS{1'b0}}, VPN}; // forces the VPN to be the same width as PPN. diff --git a/pipelined/src/muldiv/div.sv b/pipelined/src/muldiv/div.sv deleted file mode 100755 index d7f311a3f..000000000 --- a/pipelined/src/muldiv/div.sv +++ /dev/null @@ -1,1376 +0,0 @@ -/////////////////////////////////////////// -// divide4x64.sv -// -// Written: James.Stine@okstate.edu 1 February 2021 -// Modified: -// -// Purpose: Integer Divide instructions -// -// A component of the Wally configurable RISC-V project. -// -// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, -// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software -// is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -/////////////////////////////////////////// - -// *** I added these verilator controls to clean up the -// lint output. The linter warnings should be fixed, but now the output is at -// least readable. -/* verilator lint_off COMBDLY */ -/* verilator lint_off IMPLICIT */ - -module intdiv #(parameter WIDTH=64) - (Qf, remf, done, divBusy, div0, N, D, clk, reset, start, S); - - input logic [WIDTH-1:0] N, D; - input logic clk; - input logic reset; - input logic start; - input logic S; - - output logic [WIDTH-1:0] Qf; - output logic [WIDTH-1:0] remf; - output logic div0; - output logic done; - output logic divBusy; - - logic enable; - logic state0; - logic V; - logic [$clog2(WIDTH):0] Num; - logic [$clog2(WIDTH)-1:0] P, NumIter, RemShift; - logic [WIDTH-1:0] op1, op2, op1shift, Rem5; - logic [WIDTH:0] Qd, Rd, Qd2, Rd2; - logic [WIDTH-1:0] Q, rem0; - logic [3:0] quotient; - logic otfzero; - logic shiftResult; - logic enablev, state0v, donev, oftzerov, divBusyv, ulp; - - logic [WIDTH-1:0] twoD; - logic [WIDTH-1:0] twoN; - logic SignD; - logic SignN; - logic [WIDTH-1:0] QT, remT; - logic D_NegOne; - logic Max_N; - - logic otfzerov; - logic tcQ; - logic tcR; - - // Check if negative (two's complement) - // If so, convert to positive - adder #(WIDTH) cpa1 ((D ^ {WIDTH{D[WIDTH-1]&S}}), {{WIDTH-1{1'b0}}, D[WIDTH-1]&S}, twoD); - adder #(WIDTH) cpa2 ((N ^ {WIDTH{N[WIDTH-1]&S}}), {{WIDTH-1{1'b0}}, N[WIDTH-1]&S}, twoN); - assign SignD = D[WIDTH-1]; - assign SignN = N[WIDTH-1]; - // Max N and D = -1 (Overflow) - assign Max_N = (~|N[WIDTH-2:0]) & N[WIDTH-1]; - assign D_NegOne = &D; - - // Divider goes the distance to 37 cycles - // (thanks to the evil divisor for D = 0x1) - - // Shift D, if needed (for integer) - // needed to allow qst to be in range for integer - // division [1,2) and allow integer divide to work. - // - // The V or valid bit can be used to determine if D - // is 0 and thus a divide by 0 exception. This div0 - // exception is given to FSM to tell the operation to - // quit gracefully. - lzd_hier #(WIDTH) p1 (.ZP(P), .ZV(V), .B(twoD)); - shift_left #(WIDTH) p2 (twoD, P, op2); - assign op1 = twoN; - assign div0 = ~V; - - // #iter: N = m+v+s = m+2+s (mod k = 0) - // v = 2 since \rho < 1 (add 4 to make sure its a ceil) - // k = 2 (r = 2^k) - adder #($clog2(WIDTH)+1) cpa3 ({1'b0, P}, - {{$clog2(WIDTH)+1-3{1'b0}}, shiftResult, ~shiftResult, 1'b0}, - Num); - - // Determine whether need to add just Q/Rem - assign shiftResult = P[0]; - // div by 2 (ceil) - assign NumIter = Num[$clog2(WIDTH):1]; - assign RemShift = P; - - // FSM to control integer divider - // assume inputs are postive edge and - // datapath (divider) is negative edge - fsm64 #($clog2(WIDTH)) fsm1 (enablev, state0v, donev, otfzerov, divBusyv, - start, div0, NumIter, ~clk, reset); - - flopr #(1) rega (~clk, reset, donev, done); - flopr #(1) regc (~clk, reset, otfzerov, otfzero); - flopr #(1) regd (~clk, reset, enablev, enable); - flopr #(1) rege (~clk, reset, state0v, state0); - flopr #(1) regf (~clk, reset, divBusyv, divBusy); - - // To obtain a correct remainder the last bit of the - // quotient has to be aligned with a radix-r boundary. - // Since the quotient is in the range 1/2 < q < 2 (one - // integer bit and m fractional bits), this is achieved by - // shifting N right by v+s so that (m+v+s) mod k = 0. And, - // the quotient has to be aligned to the integer position. - divide4 #(WIDTH) p3 (Qd, Rd, quotient, op1, op2, clk, reset, state0, - enable, otfzero, shiftResult); - - // Storage registers to hold contents stable - flopenr #(WIDTH+1) reg3 (clk, reset, enable, Rd, Rd2); - flopenr #(WIDTH+1) reg4 (clk, reset, enable, Qd, Qd2); - - // Probably not needed - just assigns results - assign Q = Qd2[WIDTH-1:0]; - assign Rem5 = Rd2[WIDTH:1]; - - // Adjust remainder by m (no need to adjust by - shift_right #(WIDTH) p4 (Rem5, RemShift, rem0); - - // Adjust Q/Rem for Signed - assign tcQ = (SignN ^ SignD) & S; - assign tcR = SignN & S; - - // When Dividend (N) and/or Divisor (D) are negative (first bit is '1'): - // - When N and D are negative: Remainder is negative (undergoes a two's complement). - // - When N is negative: Quotient and Remainder are both negative (undergo a two's complement). - // - When D is negative: Quotient is negative (undergoes a two's complement). - adder #(WIDTH) cpa4 ((rem0 ^ {WIDTH{tcR}}), {{WIDTH-1{1'b0}}, tcR}, remT); - adder #(WIDTH) cpa5 ((Q ^ {WIDTH{tcQ}}), {{WIDTH-1{1'b0}}, tcQ}, QT); - - // RISC-V has exceptions for divide by 0 and overflow (see Table 6.1 of spec) - exception_int #(WIDTH) exc (QT, remT, N, S, div0, Max_N, D_NegOne, Qf, remf); - -endmodule // int32div - -// Division by Recurrence (r=4) -module divide4 #(parameter WIDTH=64) - (Q, rem0, quotient, op1, op2, clk, reset, state0, - enable, otfzero, shiftResult); - - input logic [WIDTH-1:0] op1, op2; - input logic clk, state0; - input logic reset; - input logic enable; - input logic otfzero; - input logic shiftResult; - - output logic [WIDTH:0] rem0; - output logic [WIDTH:0] Q; - output logic [3:0] quotient; - - logic [WIDTH+3:0] Sum, Carry; - logic [WIDTH:0] Qstar; - logic [WIDTH:0] QMstar; - logic [7:0] qtotal; - logic [WIDTH+3:0] SumN, CarryN, SumN2, CarryN2; - logic [WIDTH+3:0] divi1, divi2, divi1c, divi2c, dive1; - logic [WIDTH+3:0] mdivi_temp, mdivi; - logic zero; - logic [1:0] qsel; - logic [1:0] Qin, QMin; - logic CshiftQ, CshiftQM; - logic [WIDTH+3:0] rem1, rem2, rem3; - logic [WIDTH+3:0] SumR, CarryR; - logic [WIDTH:0] Qt; - - logic ulp; - - // Create one's complement values of Divisor (for q*D) - assign divi1 = {3'h0, op2, 1'b0}; - assign divi2 = {2'h0, op2, 2'b0}; - assign divi1c = ~divi1; - assign divi2c = ~divi2; - // Shift x1 if not mod k - mux2 #(WIDTH+4) mx1 ({3'b000, op1, 1'b0}, {4'h0, op1}, shiftResult, dive1); - - // I I I . F F F F F ... (Robertson Criteria - \rho * qmax * D) - mux2 #(WIDTH+4) mx2 ({CarryN2[WIDTH+1:0], 2'h0}, {WIDTH+4{1'b0}}, state0, CarryN); - mux2 #(WIDTH+4) mx3 ({SumN2[WIDTH+1:0], 2'h0}, dive1, state0, SumN); - // Simplify QST - adder #(8) cpa1 (SumN[WIDTH+3:WIDTH-4], CarryN[WIDTH+3:WIDTH-4], qtotal); - // q = {+2, +1, -1, -2} else q = 0 - qst4 pd1 (qtotal[7:1], divi1[WIDTH-1:WIDTH-3], quotient); - assign ulp = quotient[2]|quotient[3]; - assign zero = ~(quotient[3]|quotient[2]|quotient[1]|quotient[0]); - // Map to binary encoding - assign qsel[1] = quotient[3]|quotient[2]; - assign qsel[0] = quotient[3]|quotient[1]; - mux4 #(WIDTH+4) mx4 (divi2, divi1, divi1c, divi2c, qsel, mdivi_temp); - mux2 #(WIDTH+4) mx5 (mdivi_temp, {WIDTH+4{1'b0}}, zero, mdivi); - csa #(WIDTH+4) csa1 (mdivi, SumN, {CarryN[WIDTH+3:1], ulp}, Sum, Carry); - // regs : save CSA - flopenr #(WIDTH+4) reg1 (clk, reset, enable, Sum, SumN2); - flopenr #(WIDTH+4) reg2 (clk, reset, enable, Carry, CarryN2); - // OTF - ls_control otf1 (quotient, Qin, QMin, CshiftQ, CshiftQM); - otf #(WIDTH+1) otf2 (Qin, QMin, CshiftQ, CshiftQM, clk, - otfzero, enable, Qstar, QMstar); - - // Correction and generation of Remainder - adder #(WIDTH+4) cpa2 (SumN2[WIDTH+3:0], CarryN2[WIDTH+3:0], rem1); - // Add back +D as correction - csa #(WIDTH+4) csa2 (CarryN2[WIDTH+3:0], SumN2[WIDTH+3:0], divi1, SumR, CarryR); - adder #(WIDTH+4) cpa3 (SumR, CarryR, rem2); - // Choose remainder (Rem or Rem+D) - mux2 #(WIDTH+4) mx6 (rem1, rem2, rem1[WIDTH+3], rem3); - // Choose correct Q or QM - mux2 #(WIDTH+1) mx7 (Qstar, QMstar, rem1[WIDTH+3], Qt); - // Final results - assign rem0 = rem3[WIDTH:0]; - assign Q = Qt; - -endmodule // divide4x64 - -// Load/Control for OTFC -module ls_control (quot, Qin, QMin, CshiftQ, CshiftQM); - - input logic [3:0] quot; - - output logic [1:0] Qin; - output logic [1:0] QMin; - output logic CshiftQ; - output logic CshiftQM; - - // Load/Store Control for OTF - assign Qin[1] = (quot[1]) | (quot[3]) | (quot[0]); - assign Qin[0] = (quot[1]) | (quot[2]); - assign QMin[1] = (quot[1]) | (!quot[3]&!quot[2]&!quot[1]&!quot[0]); - assign QMin[0] = (quot[3]) | (quot[0]) | - (!quot[3]&!quot[2]&!quot[1]&!quot[0]); - assign CshiftQ = (quot[1]) | (quot[0]); - assign CshiftQM = (quot[3]) | (quot[2]); - -endmodule - -// On-the-fly Conversion (OTFC) -module otf #(parameter WIDTH=8) - (Qin, QMin, CshiftQ, CshiftQM, clk, reset, enable, R2Q, R1Q); - - input logic [1:0] Qin, QMin; - input logic CshiftQ, CshiftQM; - input logic clk; - input logic reset; - input logic enable; - - output logic [WIDTH-1:0] R2Q; - output logic [WIDTH-1:0] R1Q; - - logic [WIDTH-1:0] Qstar, QMstar; - logic [WIDTH-1:0] M1Q, M2Q; - - // QM - mux2 #(WIDTH) m1 (QMstar, Qstar, CshiftQM, M1Q); - flopenr #(WIDTH) r1 (clk, reset, enable, {M1Q[WIDTH-3:0], QMin}, R1Q); - // Q - mux2 #(WIDTH) m2 (Qstar, QMstar, CshiftQ, M2Q); - flopenr #(WIDTH) r2 (clk, reset, enable, {M2Q[WIDTH-3:0], Qin}, R2Q); - - assign Qstar = R2Q; - assign QMstar = R1Q; - -endmodule // otf8 -/* -module adder #(parameter WIDTH=8) (input logic [WIDTH-1:0] a, b, - output logic [WIDTH-1:0] y); - - assign y = a + b; - -endmodule // adder -*/ - -module fa (input logic a, b, c, output logic sum, carry); - - assign sum = a^b^c; - assign carry = a&b|a&c|b&c; - -endmodule // fa - -module csa #(parameter WIDTH=8) (input logic [WIDTH-1:0] a, b, c, - output logic [WIDTH-1:0] sum, carry); - - logic [WIDTH:0] carry_temp; - genvar i; - generate - for (i=0;i B. LT and GT are both '0' if A = B. - -module magcompare2b (LT, GT, A, B); - - input logic [1:0] A; - input logic [1:0] B; - - output logic LT; - output logic GT; - - // Determine if A < B using a minimized sum-of-products expression - assign LT = ~A[1]&B[1] | ~A[1]&~A[0]&B[0] | ~A[0]&B[1]&B[0]; - // Determine if A > B using a minimized sum-of-products expression - assign GT = A[1]&~B[1] | A[1]&A[0]&~B[0] | A[0]&~B[1]&~B[0]; - -endmodule // magcompare2b - -// J. E. Stine and M. J. Schulte, "A combined two's complement and -// floating-point comparator," 2005 IEEE International Symposium on -// Circuits and Systems, Kobe, 2005, pp. 89-92 Vol. 1. -// doi: 10.1109/ISCAS.2005.1464531 - -module magcompare8 (LT, EQ, A, B); - - input logic [7:0] A; - input logic [7:0] B; - - logic [3:0] s; - logic [3:0] t; - logic [1:0] u; - logic [1:0] v; - logic GT; - //wire LT; - - output logic EQ; - output logic LT; - - magcompare2b mag1 (s[0], t[0], A[1:0], B[1:0]); - magcompare2b mag2 (s[1], t[1], A[3:2], B[3:2]); - magcompare2b mag3 (s[2], t[2], A[5:4], B[5:4]); - magcompare2b mag4 (s[3], t[3], A[7:6], B[7:6]); - - magcompare2b mag5 (u[0], v[0], t[1:0], s[1:0]); - magcompare2b mag6 (u[1], v[1], t[3:2], s[3:2]); - - magcompare2b mag7 (LT, GT, v[1:0], u[1:0]); - - assign EQ = ~(GT | LT); - -endmodule // magcompare8 - -// RISC-V Exception Logic for Divide by 0 and Overflow (Signed Integer Divide) -module exception_int #(parameter WIDTH=8) - (Q, rem, op1, S, div0, Max_N, D_NegOne, Qf, remf); - - input logic [WIDTH-1:0] Q; - input logic [WIDTH-1:0] rem; - input logic [WIDTH-1:0] op1; - input logic S; - input logic div0; - input logic Max_N; - input logic D_NegOne; - - output logic [WIDTH-1:0] Qf; - output logic [WIDTH-1:0] remf; - - always_comb - case ({div0, S, Max_N, D_NegOne}) - 4'b0000 : Qf = Q; - 4'b0001 : Qf = Q; - 4'b0010 : Qf = Q; - 4'b0011 : Qf = Q; - 4'b0100 : Qf = Q; - 4'b0101 : Qf = Q; - 4'b0110 : Qf = Q; - 4'b0111 : Qf = {1'b1, {WIDTH-1{1'h0}}}; - 4'b1000 : Qf = {WIDTH{1'b1}}; - 4'b1001 : Qf = {WIDTH{1'b1}}; - 4'b1010 : Qf = {WIDTH{1'b1}}; - 4'b1011 : Qf = {WIDTH{1'b1}}; - 4'b1100 : Qf = {WIDTH{1'b1}}; - 4'b1101 : Qf = {WIDTH{1'b1}}; - 4'b1110 : Qf = {WIDTH{1'b1}}; - 4'b1111 : Qf = {WIDTH{1'b1}}; - default: Qf = Q; - endcase - - always_comb - case ({div0, S, Max_N, D_NegOne}) - 4'b0000 : remf = rem; - 4'b0001 : remf = rem; - 4'b0010 : remf = rem; - 4'b0011 : remf = rem; - 4'b0100 : remf = rem; - 4'b0101 : remf = rem; - 4'b0110 : remf = rem; - 4'b0111 : remf = {WIDTH{1'h0}}; - 4'b1000 : remf = op1; - 4'b1001 : remf = op1; - 4'b1010 : remf = op1; - 4'b1011 : remf = op1; - 4'b1100 : remf = op1; - 4'b1101 : remf = op1; - 4'b1110 : remf = op1; - 4'b1111 : remf = op1; - default: remf = rem; - endcase - -endmodule // exception_int - -/* verilator lint_on COMBDLY */ -/* verilator lint_on IMPLICIT */ diff --git a/pipelined/src/muldiv/intdivrestoring.sv b/pipelined/src/muldiv/intdivrestoring.sv index 04eba4af3..c64c01084 100644 --- a/pipelined/src/muldiv/intdivrestoring.sv +++ b/pipelined/src/muldiv/intdivrestoring.sv @@ -60,15 +60,13 @@ module intdivrestoring ( assign DivBusyE = (state == BUSY) | DivStartE; // Handle sign extension for W-type instructions - generate - if (`XLEN == 64) begin:rv64 // RV64 has W-type instructions - mux2 #(`XLEN) xinmux(ForwardedSrcAE, {ForwardedSrcAE[31:0], 32'b0}, W64E, XinE); - mux2 #(`XLEN) dinmux(ForwardedSrcBE, {{32{ForwardedSrcBE[31]&DivSignedE}}, ForwardedSrcBE[31:0]}, W64E, DinE); - end else begin // RV32 has no W-type instructions - assign XinE = ForwardedSrcAE; - assign DinE = ForwardedSrcBE; + if (`XLEN == 64) begin:rv64 // RV64 has W-type instructions + mux2 #(`XLEN) xinmux(ForwardedSrcAE, {ForwardedSrcAE[31:0], 32'b0}, W64E, XinE); + mux2 #(`XLEN) dinmux(ForwardedSrcBE, {{32{ForwardedSrcBE[31]&DivSignedE}}, ForwardedSrcBE[31:0]}, W64E, DinE); + end else begin // RV32 has no W-type instructions + assign XinE = ForwardedSrcAE; + assign DinE = ForwardedSrcBE; end - endgenerate // Extract sign bits and check fo division by zero assign SignDE = DivSignedE & DinE[`XLEN-1]; @@ -97,11 +95,9 @@ module intdivrestoring ( flopen #(3) Div0eMReg(clk, DivStartE, {Div0E, NegQE, SignXE}, {Div0M, NegQM, NegWM}); // one copy of divstep for each bit produced per cycle - generate - genvar i; - for (i=0; i<`DIV_BITSPERCYCLE; i = i+1) - intdivrestoringstep divstep(WM[i], XQM[i], DAbsBM, WM[i+1], XQM[i+1]); - endgenerate + genvar i; + for (i=0; i<`DIV_BITSPERCYCLE; i = i+1) + intdivrestoringstep divstep(WM[i], XQM[i], DAbsBM, WM[i+1], XQM[i+1]); // On final setp of signed operations, negate outputs as needed to get correct sign neg #(`XLEN) qneg(XQM[0], XQnM); diff --git a/pipelined/src/muldiv/mul.sv b/pipelined/src/muldiv/mul.sv index e1174a9cc..565a5d640 100644 --- a/pipelined/src/muldiv/mul.sv +++ b/pipelined/src/muldiv/mul.sv @@ -49,8 +49,8 @@ module mul ( // Signed * Unsigned = P' + ( PA - PB)*2^(XLEN-1) - PP*2^(2XLEN-2) // Unsigned * Unsigned = P' + ( PA + PB)*2^(XLEN-1) + PP*2^(2XLEN-2) - logic [`XLEN*2-1:0] PP0E, PP1E, PP2E, PP3E, PP4E; - logic [`XLEN*2-1:0] PP0M, PP1M, PP2M, PP3M, PP4M; + logic [`XLEN*2-1:0] PP1E, PP2E, PP3E, PP4E; + logic [`XLEN*2-1:0] PP1M, PP2M, PP3M, PP4M; logic [`XLEN-2:0] PA, PB; logic PP; logic MULH, MULHSU; @@ -62,7 +62,7 @@ module mul ( assign Aprime = {1'b0, ForwardedSrcAE[`XLEN-2:0]}; assign Bprime = {1'b0, ForwardedSrcBE[`XLEN-2:0]}; - redundantmul #(`XLEN) bigmul(.a(Aprime), .b(Bprime), .out0(PP0E), .out1(PP1E)); + assign PP1E = Aprime * Bprime; assign PA = {(`XLEN-1){ForwardedSrcAE[`XLEN-1]}} & ForwardedSrcBE[`XLEN-2:0]; assign PB = {(`XLEN-1){ForwardedSrcBE[`XLEN-1]}} & ForwardedSrcAE[`XLEN-2:0]; assign PP = ForwardedSrcAE[`XLEN-1] & ForwardedSrcBE[`XLEN-1]; @@ -83,12 +83,11 @@ module mul ( // Memory Stage: Sum partial proudcts ////////////////////////////// - flopenrc #(`XLEN*2) PP0Reg(clk, reset, FlushM, ~StallM, PP0E, PP0M); flopenrc #(`XLEN*2) PP1Reg(clk, reset, FlushM, ~StallM, PP1E, PP1M); flopenrc #(`XLEN*2) PP2Reg(clk, reset, FlushM, ~StallM, PP2E, PP2M); flopenrc #(`XLEN*2) PP3Reg(clk, reset, FlushM, ~StallM, PP3E, PP3M); flopenrc #(`XLEN*2) PP4Reg(clk, reset, FlushM, ~StallM, PP4E, PP4M); - assign ProdM = PP0M + PP1M + PP2M + PP3M + PP4M; //ForwardedSrcAE * ForwardedSrcBE; + assign ProdM = PP1M + PP2M + PP3M + PP4M; //ForwardedSrcAE * ForwardedSrcBE; endmodule diff --git a/pipelined/src/muldiv/muldiv.sv b/pipelined/src/muldiv/muldiv.sv index a1e76616c..e51bec2f1 100644 --- a/pipelined/src/muldiv/muldiv.sv +++ b/pipelined/src/muldiv/muldiv.sv @@ -74,13 +74,11 @@ module muldiv ( // Handle sign extension for W-type instructions flopenrc #(1) W64MReg(clk, reset, FlushM, ~StallM, W64E, W64M); - generate - if (`XLEN == 64) begin:resmux // RV64 has W-type instructions - assign MulDivResultM = W64M ? {{32{PrelimResultM[31]}}, PrelimResultM[31:0]} : PrelimResultM; - end else begin:resmux // RV32 has no W-type instructions - assign MulDivResultM = PrelimResultM; - end - endgenerate + if (`XLEN == 64) begin:resmux // RV64 has W-type instructions + assign MulDivResultM = W64M ? {{32{PrelimResultM[31]}}, PrelimResultM[31:0]} : PrelimResultM; + end else begin:resmux // RV32 has no W-type instructions + assign MulDivResultM = PrelimResultM; + end // Writeback stage pipeline register flopenrc #(`XLEN) MulDivResultWReg(clk, reset, FlushW, ~StallW, MulDivResultM, MulDivResultW); diff --git a/pipelined/src/privileged/csrc.sv b/pipelined/src/privileged/csrc.sv index bd529e6c2..4e75486d3 100644 --- a/pipelined/src/privileged/csrc.sv +++ b/pipelined/src/privileged/csrc.sv @@ -56,111 +56,109 @@ module csrc #(parameter output logic IllegalCSRCAccessM ); - generate - if (`ZICOUNTERS_SUPPORTED) begin:counters - (* mark_debug = "true" *) logic [63:0] CYCLE_REGW, INSTRET_REGW; - logic [63:0] CYCLEPlusM, INSTRETPlusM; - logic [`XLEN-1:0] NextCYCLEM, NextINSTRETM; - logic WriteCYCLEM, WriteINSTRETM; - logic [4:0] CounterNumM; - logic [`XLEN-1:0] HPMCOUNTER_REGW[`COUNTERS-1:0]; - logic [`XLEN-1:0] HPMCOUNTERH_REGW[`COUNTERS-1:0]; - logic InstrValidNotFlushedM; - logic LoadStallE, LoadStallM; - logic [`COUNTERS-1:0] WriteHPMCOUNTERM; - logic [`COUNTERS-1:0] CounterEvent; - logic [63:0] HPMCOUNTERPlusM[`COUNTERS-1:0]; - logic [`XLEN-1:0] NextHPMCOUNTERM[`COUNTERS-1:0]; - genvar i; + if (`ZICOUNTERS_SUPPORTED) begin:counters + (* mark_debug = "true" *) logic [63:0] CYCLE_REGW, INSTRET_REGW; + logic [63:0] CYCLEPlusM, INSTRETPlusM; + logic [`XLEN-1:0] NextCYCLEM, NextINSTRETM; + logic WriteCYCLEM, WriteINSTRETM; + logic [4:0] CounterNumM; + logic [`XLEN-1:0] HPMCOUNTER_REGW[`COUNTERS-1:0]; + logic [`XLEN-1:0] HPMCOUNTERH_REGW[`COUNTERS-1:0]; + logic InstrValidNotFlushedM; + logic LoadStallE, LoadStallM; + logic [`COUNTERS-1:0] WriteHPMCOUNTERM; + logic [`COUNTERS-1:0] CounterEvent; + logic [63:0] HPMCOUNTERPlusM[`COUNTERS-1:0]; + logic [`XLEN-1:0] NextHPMCOUNTERM[`COUNTERS-1:0]; + genvar i; - // Interface signals - flopenrc #(1) LoadStallEReg(.clk, .reset, .clear(1'b0), .en(~StallE), .d(LoadStallD), .q(LoadStallE)); // don't flush the load stall during a load stall. - flopenrc #(1) LoadStallMReg(.clk, .reset, .clear(FlushM), .en(~StallM), .d(LoadStallE), .q(LoadStallM)); - assign InstrValidNotFlushedM = InstrValidM & ~StallW & ~FlushW; - - // Determine when to increment each counter - assign CounterEvent[0] = 1'b1; // MCYCLE always increments - assign CounterEvent[1] = 1'b0; // Counter 0 doesn't exist - assign CounterEvent[2] = InstrValidNotFlushedM; - if(`QEMU) begin // No other performance counters in QEMU - assign CounterEvent[`COUNTERS-1:3] = 0; - end else begin // User-defined counters - assign CounterEvent[3] = LoadStallM; // don't want to suppress on flush as this only happens if flushed. - assign CounterEvent[4] = BPPredDirWrongM & InstrValidNotFlushedM; - assign CounterEvent[5] = InstrClassM[0] & InstrValidNotFlushedM; - assign CounterEvent[6] = BTBPredPCWrongM & InstrValidNotFlushedM; - assign CounterEvent[7] = (InstrClassM[4] | InstrClassM[2] | InstrClassM[1]) & InstrValidNotFlushedM; - assign CounterEvent[8] = RASPredPCWrongM & InstrValidNotFlushedM; - assign CounterEvent[9] = InstrClassM[3] & InstrValidNotFlushedM; - assign CounterEvent[10] = BPPredClassNonCFIWrongM & InstrValidNotFlushedM; - assign CounterEvent[11] = DCacheAccess; - assign CounterEvent[12] = DCacheMiss; - assign CounterEvent[`COUNTERS-1:13] = 0; // eventually give these sources, including FP instructions, I$/D$ misses, branches and mispredictions - end - - // Counter update and write logic - for (i = 0; i < `COUNTERS; i = i+1) begin - assign WriteHPMCOUNTERM[i] = CSRMWriteM & (CSRAdrM == MHPMCOUNTERBASE + i); - assign NextHPMCOUNTERM[i][`XLEN-1:0] = WriteHPMCOUNTERM[i] ? CSRWriteValM : HPMCOUNTERPlusM[i][`XLEN-1:0]; - always_ff @(posedge clk) //, posedge reset) // ModelSim doesn't like syntax of passing array element to flop - if (reset) HPMCOUNTER_REGW[i][`XLEN-1:0] <= #1 0; - else HPMCOUNTER_REGW[i][`XLEN-1:0] <= #1 NextHPMCOUNTERM[i]; - - if (`XLEN==32) begin // write high and low separately - logic [`COUNTERS-1:0] WriteHPMCOUNTERHM; - logic [`XLEN-1:0] NextHPMCOUNTERHM[`COUNTERS-1:0]; - assign HPMCOUNTERPlusM[i] = {HPMCOUNTERH_REGW[i], HPMCOUNTER_REGW[i]} + {63'b0, CounterEvent[i] & ~MCOUNTINHIBIT_REGW[i]}; - assign WriteHPMCOUNTERHM[i] = CSRMWriteM & (CSRAdrM == MHPMCOUNTERHBASE + i); - assign NextHPMCOUNTERHM[i] = WriteHPMCOUNTERHM[i] ? CSRWriteValM : HPMCOUNTERPlusM[i][63:32]; - always_ff @(posedge clk) //, posedge reset) // ModelSim doesn't like syntax of passing array element to flop - if (reset) HPMCOUNTERH_REGW[i][`XLEN-1:0] <= #1 0; - else HPMCOUNTERH_REGW[i][`XLEN-1:0] <= #1 NextHPMCOUNTERHM[i]; - end else begin // XLEN=64; write entire register - assign HPMCOUNTERPlusM[i] = HPMCOUNTER_REGW[i] + {63'b0, CounterEvent[i] & ~MCOUNTINHIBIT_REGW[i]}; - end - end - - // Read Counters, or cause excepiton if insufficient privilege in light of COUNTEREN flags - assign CounterNumM = CSRAdrM[4:0]; // which counter to read? - always_comb - if (PrivilegeModeW == `M_MODE | - MCOUNTEREN_REGW[CounterNumM] & (!`S_SUPPORTED | PrivilegeModeW == `S_MODE | SCOUNTEREN_REGW[CounterNumM])) begin - IllegalCSRCAccessM = 0; - if (`XLEN==64) begin // 64-bit counter reads - // Veri lator doesn't realize this only occurs for XLEN=64 - /* verilator lint_off WIDTH */ - if (CSRAdrM == TIME) CSRCReadValM = MTIME_CLINT; // TIME register is a shadow of the memory-mapped MTIME from the CLINT - /* verilator lint_on WIDTH */ - else if (CSRAdrM >= MHPMCOUNTERBASE & CSRAdrM < MHPMCOUNTERBASE+`COUNTERS) CSRCReadValM = HPMCOUNTER_REGW[CounterNumM]; - else if (CSRAdrM >= HPMCOUNTERBASE & CSRAdrM < HPMCOUNTERBASE+`COUNTERS) CSRCReadValM = HPMCOUNTER_REGW[CounterNumM]; - else begin - CSRCReadValM = 0; - IllegalCSRCAccessM = 1; // requested CSR doesn't exist - end - end else begin // 32-bit counter reads - // Veri lator doesn't realize this only occurs for XLEN=32 - /* verilator lint_off WIDTH */ - if (CSRAdrM == TIME) CSRCReadValM = MTIME_CLINT[31:0];// TIME register is a shadow of the memory-mapped MTIME from the CLINT - else if (CSRAdrM == TIMEH) CSRCReadValM = MTIME_CLINT[63:32]; - /* verilator lint_on WIDTH */ - else if (CSRAdrM >= MHPMCOUNTERBASE & CSRAdrM < MHPMCOUNTERBASE+`COUNTERS) CSRCReadValM = HPMCOUNTER_REGW[CounterNumM]; - else if (CSRAdrM >= HPMCOUNTERBASE & CSRAdrM < HPMCOUNTERBASE+`COUNTERS) CSRCReadValM = HPMCOUNTER_REGW[CounterNumM]; - else if (CSRAdrM >= MHPMCOUNTERHBASE & CSRAdrM < MHPMCOUNTERHBASE+`COUNTERS) CSRCReadValM = HPMCOUNTERH_REGW[CounterNumM]; - else if (CSRAdrM >= HPMCOUNTERHBASE & CSRAdrM < HPMCOUNTERHBASE+`COUNTERS) CSRCReadValM = HPMCOUNTERH_REGW[CounterNumM]; - else begin - CSRCReadValM = 0; - IllegalCSRCAccessM = 1; // requested CSR doesn't exist - end - end - end else begin - CSRCReadValM = 0; - IllegalCSRCAccessM = 1; // no privileges for this csr - end - end else begin - assign CSRCReadValM = 0; - assign IllegalCSRCAccessM = 1; // counters aren't enabled + // Interface signals + flopenrc #(1) LoadStallEReg(.clk, .reset, .clear(1'b0), .en(~StallE), .d(LoadStallD), .q(LoadStallE)); // don't flush the load stall during a load stall. + flopenrc #(1) LoadStallMReg(.clk, .reset, .clear(FlushM), .en(~StallM), .d(LoadStallE), .q(LoadStallM)); + assign InstrValidNotFlushedM = InstrValidM & ~StallW & ~FlushW; + + // Determine when to increment each counter + assign CounterEvent[0] = 1'b1; // MCYCLE always increments + assign CounterEvent[1] = 1'b0; // Counter 0 doesn't exist + assign CounterEvent[2] = InstrValidNotFlushedM; + if(`QEMU) begin: cevent // No other performance counters in QEMU + assign CounterEvent[`COUNTERS-1:3] = 0; + end else begin: cevent // User-defined counters + assign CounterEvent[3] = LoadStallM; // don't want to suppress on flush as this only happens if flushed. + assign CounterEvent[4] = BPPredDirWrongM & InstrValidNotFlushedM; + assign CounterEvent[5] = InstrClassM[0] & InstrValidNotFlushedM; + assign CounterEvent[6] = BTBPredPCWrongM & InstrValidNotFlushedM; + assign CounterEvent[7] = (InstrClassM[4] | InstrClassM[2] | InstrClassM[1]) & InstrValidNotFlushedM; + assign CounterEvent[8] = RASPredPCWrongM & InstrValidNotFlushedM; + assign CounterEvent[9] = InstrClassM[3] & InstrValidNotFlushedM; + assign CounterEvent[10] = BPPredClassNonCFIWrongM & InstrValidNotFlushedM; + assign CounterEvent[11] = DCacheAccess; + assign CounterEvent[12] = DCacheMiss; + assign CounterEvent[`COUNTERS-1:13] = 0; // eventually give these sources, including FP instructions, I$/D$ misses, branches and mispredictions end - endgenerate + + // Counter update and write logic + for (i = 0; i < `COUNTERS; i = i+1) begin:cntr + assign WriteHPMCOUNTERM[i] = CSRMWriteM & (CSRAdrM == MHPMCOUNTERBASE + i); + assign NextHPMCOUNTERM[i][`XLEN-1:0] = WriteHPMCOUNTERM[i] ? CSRWriteValM : HPMCOUNTERPlusM[i][`XLEN-1:0]; + always_ff @(posedge clk) //, posedge reset) // ModelSim doesn't like syntax of passing array element to flop + if (reset) HPMCOUNTER_REGW[i][`XLEN-1:0] <= #1 0; + else HPMCOUNTER_REGW[i][`XLEN-1:0] <= #1 NextHPMCOUNTERM[i]; + + if (`XLEN==32) begin // write high and low separately + logic [`COUNTERS-1:0] WriteHPMCOUNTERHM; + logic [`XLEN-1:0] NextHPMCOUNTERHM[`COUNTERS-1:0]; + assign HPMCOUNTERPlusM[i] = {HPMCOUNTERH_REGW[i], HPMCOUNTER_REGW[i]} + {63'b0, CounterEvent[i] & ~MCOUNTINHIBIT_REGW[i]}; + assign WriteHPMCOUNTERHM[i] = CSRMWriteM & (CSRAdrM == MHPMCOUNTERHBASE + i); + assign NextHPMCOUNTERHM[i] = WriteHPMCOUNTERHM[i] ? CSRWriteValM : HPMCOUNTERPlusM[i][63:32]; + always_ff @(posedge clk) //, posedge reset) // ModelSim doesn't like syntax of passing array element to flop + if (reset) HPMCOUNTERH_REGW[i][`XLEN-1:0] <= #1 0; + else HPMCOUNTERH_REGW[i][`XLEN-1:0] <= #1 NextHPMCOUNTERHM[i]; + end else begin // XLEN=64; write entire register + assign HPMCOUNTERPlusM[i] = HPMCOUNTER_REGW[i] + {63'b0, CounterEvent[i] & ~MCOUNTINHIBIT_REGW[i]}; + end + end + + // Read Counters, or cause excepiton if insufficient privilege in light of COUNTEREN flags + assign CounterNumM = CSRAdrM[4:0]; // which counter to read? + always_comb + if (PrivilegeModeW == `M_MODE | + MCOUNTEREN_REGW[CounterNumM] & (!`S_SUPPORTED | PrivilegeModeW == `S_MODE | SCOUNTEREN_REGW[CounterNumM])) begin + IllegalCSRCAccessM = 0; + if (`XLEN==64) begin // 64-bit counter reads + // Veri lator doesn't realize this only occurs for XLEN=64 + /* verilator lint_off WIDTH */ + if (CSRAdrM == TIME) CSRCReadValM = MTIME_CLINT; // TIME register is a shadow of the memory-mapped MTIME from the CLINT + /* verilator lint_on WIDTH */ + else if (CSRAdrM >= MHPMCOUNTERBASE & CSRAdrM < MHPMCOUNTERBASE+`COUNTERS) CSRCReadValM = HPMCOUNTER_REGW[CounterNumM]; + else if (CSRAdrM >= HPMCOUNTERBASE & CSRAdrM < HPMCOUNTERBASE+`COUNTERS) CSRCReadValM = HPMCOUNTER_REGW[CounterNumM]; + else begin + CSRCReadValM = 0; + IllegalCSRCAccessM = 1; // requested CSR doesn't exist + end + end else begin // 32-bit counter reads + // Veri lator doesn't realize this only occurs for XLEN=32 + /* verilator lint_off WIDTH */ + if (CSRAdrM == TIME) CSRCReadValM = MTIME_CLINT[31:0];// TIME register is a shadow of the memory-mapped MTIME from the CLINT + else if (CSRAdrM == TIMEH) CSRCReadValM = MTIME_CLINT[63:32]; + /* verilator lint_on WIDTH */ + else if (CSRAdrM >= MHPMCOUNTERBASE & CSRAdrM < MHPMCOUNTERBASE+`COUNTERS) CSRCReadValM = HPMCOUNTER_REGW[CounterNumM]; + else if (CSRAdrM >= HPMCOUNTERBASE & CSRAdrM < HPMCOUNTERBASE+`COUNTERS) CSRCReadValM = HPMCOUNTER_REGW[CounterNumM]; + else if (CSRAdrM >= MHPMCOUNTERHBASE & CSRAdrM < MHPMCOUNTERHBASE+`COUNTERS) CSRCReadValM = HPMCOUNTERH_REGW[CounterNumM]; + else if (CSRAdrM >= HPMCOUNTERHBASE & CSRAdrM < HPMCOUNTERHBASE+`COUNTERS) CSRCReadValM = HPMCOUNTERH_REGW[CounterNumM]; + else begin + CSRCReadValM = 0; + IllegalCSRCAccessM = 1; // requested CSR doesn't exist + end + end + end else begin + CSRCReadValM = 0; + IllegalCSRCAccessM = 1; // no privileges for this csr + end + end else begin + assign CSRCReadValM = 0; + assign IllegalCSRCAccessM = 1; // counters aren't enabled + end endmodule // To Do: diff --git a/pipelined/src/privileged/csri.sv b/pipelined/src/privileged/csri.sv index 9e4d7850a..81ddf88a0 100644 --- a/pipelined/src/privileged/csri.sv +++ b/pipelined/src/privileged/csri.sv @@ -66,58 +66,54 @@ module csri #(parameter assign WriteSIPM = CSRSWriteM & (CSRAdrM == SIP) & ~StallW; assign WriteSIEM = CSRSWriteM & (CSRAdrM == SIE) & ~StallW; - // Interrupt Pending and Enable Registers - // MEIP, MTIP, MSIP are read-only - // SEIP, STIP, SSIP is writable in MIP if S mode exists - // SSIP is writable in SIP if S mode exists - generate - if (`S_SUPPORTED) begin:mask - assign MIP_WRITE_MASK = 12'h222; // SEIP, STIP, SSIP are writable in MIP (20210108-draft 3.1.9) - assign SIP_WRITE_MASK = 12'h002; // SSIP is writable in SIP (privileged 20210108-draft 4.1.3) - end else begin:mask - assign MIP_WRITE_MASK = 12'h000; - assign SIP_WRITE_MASK = 12'h000; - end - always @(posedge clk) //, posedge reset) begin // *** I strongly feel that IntInM should go directly to IP_REGW -- Ben 9/7/21 - if (reset) IP_REGW_writeable <= 10'b0; - else if (WriteMIPM) IP_REGW_writeable <= (CSRWriteValM[9:0] & MIP_WRITE_MASK[9:0]) | IntInM[9:0]; // MTIP unclearable - else if (WriteSIPM) IP_REGW_writeable <= (CSRWriteValM[9:0] & SIP_WRITE_MASK[9:0]) | IntInM[9:0]; // MTIP unclearable +// Interrupt Pending and Enable Registers +// MEIP, MTIP, MSIP are read-only +// SEIP, STIP, SSIP is writable in MIP if S mode exists +// SSIP is writable in SIP if S mode exists + if (`S_SUPPORTED) begin:mask + assign MIP_WRITE_MASK = 12'h222; // SEIP, STIP, SSIP are writable in MIP (20210108-draft 3.1.9) + assign SIP_WRITE_MASK = 12'h002; // SSIP is writable in SIP (privileged 20210108-draft 4.1.3) + end else begin:mask + assign MIP_WRITE_MASK = 12'h000; + assign SIP_WRITE_MASK = 12'h000; + end + always @(posedge clk) //, posedge reset) begin // *** I strongly feel that IntInM should go directly to IP_REGW -- Ben 9/7/21 + if (reset) IP_REGW_writeable <= 10'b0; + else if (WriteMIPM) IP_REGW_writeable <= (CSRWriteValM[9:0] & MIP_WRITE_MASK[9:0]) | IntInM[9:0]; // MTIP unclearable + else if (WriteSIPM) IP_REGW_writeable <= (CSRWriteValM[9:0] & SIP_WRITE_MASK[9:0]) | IntInM[9:0]; // MTIP unclearable // else if (WriteUIPM) IP_REGW = (CSRWriteValM & 12'hBBB) | (NextIPM & 12'h080); // MTIP unclearable - else IP_REGW_writeable <= IP_REGW_writeable | IntInM[9:0]; // *** check this turns off interrupts properly even when MIDELEG changes - always @(posedge clk) //, posedge reset) begin - if (reset) IE_REGW <= 12'b0; - else if (WriteMIEM) IE_REGW <= (CSRWriteValM[11:0] & 12'hAAA); // MIE controls M and S fields - else if (WriteSIEM) IE_REGW <= (CSRWriteValM[11:0] & 12'h222) | (IE_REGW & 12'h888); // only S fields + else IP_REGW_writeable <= IP_REGW_writeable | IntInM[9:0]; // *** check this turns off interrupts properly even when MIDELEG changes + always @(posedge clk) //, posedge reset) begin + if (reset) IE_REGW <= 12'b0; + else if (WriteMIEM) IE_REGW <= (CSRWriteValM[11:0] & 12'hAAA); // MIE controls M and S fields + else if (WriteSIEM) IE_REGW <= (CSRWriteValM[11:0] & 12'h222) | (IE_REGW & 12'h888); // only S fields // else if (WriteUIEM) IE_REGW = (CSRWriteValM & 12'h111) | (IE_REGW & 12'hAAA); // only U field - endgenerate // restricted views of registers - generate - always_comb begin:regs - // Add MEIP read-only signal - IP_REGW = {IntInM[11],1'b0,IP_REGW_writeable}; + always_comb begin:regs + // Add MEIP read-only signal + IP_REGW = {IntInM[11],1'b0,IP_REGW_writeable}; - // Machine Mode - MIP_REGW = IP_REGW; - MIE_REGW = IE_REGW; + // Machine Mode + MIP_REGW = IP_REGW; + MIE_REGW = IE_REGW; - // Supervisor mode - if (`S_SUPPORTED) begin - SIP_REGW = IP_REGW & MIDELEG_REGW[11:0] & 'h222; // only delegated interrupts visible - SIE_REGW = IE_REGW & MIDELEG_REGW[11:0] & 'h222; - end else begin - SIP_REGW = 12'b0; - SIE_REGW = 12'b0; - end - - // User Modes iterrupts depricated - /*if (`U_SUPPORTED & `N_SUPPORTED) begin - UIP_REGW = IP_REGW & MIDELEG_REGW & SIDELEG_REGW & 'h111; // only delegated interrupts visible - UIE_REGW = IE_REGW & MIDELEG_REGW & SIDELEG_REGW & 'h111; // only delegated interrupts visible - end else begin - UIP_REGW = 12'b0; - UIE_REGW = 12'b0; - end */ + // Supervisor mode + if (`S_SUPPORTED) begin + SIP_REGW = IP_REGW & MIDELEG_REGW[11:0] & 'h222; // only delegated interrupts visible + SIE_REGW = IE_REGW & MIDELEG_REGW[11:0] & 'h222; + end else begin + SIP_REGW = 12'b0; + SIE_REGW = 12'b0; end - endgenerate + + // User Modes iterrupts depricated + /*if (`U_SUPPORTED & `N_SUPPORTED) begin + UIP_REGW = IP_REGW & MIDELEG_REGW & SIDELEG_REGW & 'h111; // only delegated interrupts visible + UIE_REGW = IE_REGW & MIDELEG_REGW & SIDELEG_REGW & 'h111; // only delegated interrupts visible + end else begin + UIP_REGW = 12'b0; + UIE_REGW = 12'b0; + end */ + end endmodule diff --git a/pipelined/src/privileged/csrm.sv b/pipelined/src/privileged/csrm.sv index 17a917d20..3807df8f6 100644 --- a/pipelined/src/privileged/csrm.sv +++ b/pipelined/src/privileged/csrm.sv @@ -92,32 +92,30 @@ module csrm #(parameter // There are PMP_ENTRIES = 0, 16, or 64 PMPADDR registers, each of which has its own flop genvar i; - generate - if (`PMP_ENTRIES > 0) begin:pmp - logic [`PMP_ENTRIES-1:0] WritePMPCFGM; - logic [`PMP_ENTRIES-1:0] WritePMPADDRM ; - logic [`PMP_ENTRIES-1:0] ADDRLocked, CFGLocked; - for(i=0; i<`PMP_ENTRIES; i++) begin - // when the lock bit is set, don't allow writes to the PMPCFG or PMPADDR - // also, when the lock bit of the next entry is set and the next entry is TOR, don't allow writes to this entry PMPADDR - assign CFGLocked[i] = PMPCFG_ARRAY_REGW[i][7]; - if (i == `PMP_ENTRIES-1) - assign ADDRLocked[i] = PMPCFG_ARRAY_REGW[i][7]; - else - assign ADDRLocked[i] = PMPCFG_ARRAY_REGW[i][7] | (PMPCFG_ARRAY_REGW[i+1][7] & PMPCFG_ARRAY_REGW[i+1][4:3] == 2'b01); - - assign WritePMPADDRM[i] = (CSRMWriteM & (CSRAdrM == (PMPADDR0+i))) & ~StallW & ~ADDRLocked[i]; - flopenr #(`XLEN) PMPADDRreg(clk, reset, WritePMPADDRM[i], CSRWriteValM, PMPADDR_ARRAY_REGW[i]); - if (`XLEN==64) begin - assign WritePMPCFGM[i] = (CSRMWriteM & (CSRAdrM == (PMPCFG0+2*(i/8)))) & ~StallW & ~CFGLocked[i]; - flopenr #(8) PMPCFGreg(clk, reset, WritePMPCFGM[i], CSRWriteValM[(i%8)*8+7:(i%8)*8], PMPCFG_ARRAY_REGW[i]); - end else begin - assign WritePMPCFGM[i] = (CSRMWriteM & (CSRAdrM == (PMPCFG0+i/4))) & ~StallW & ~CFGLocked[i]; - flopenr #(8) PMPCFGreg(clk, reset, WritePMPCFGM[i], CSRWriteValM[(i%4)*8+7:(i%4)*8], PMPCFG_ARRAY_REGW[i]); - end + if (`PMP_ENTRIES > 0) begin:pmp + logic [`PMP_ENTRIES-1:0] WritePMPCFGM; + logic [`PMP_ENTRIES-1:0] WritePMPADDRM ; + logic [`PMP_ENTRIES-1:0] ADDRLocked, CFGLocked; + for(i=0; i<`PMP_ENTRIES; i++) begin + // when the lock bit is set, don't allow writes to the PMPCFG or PMPADDR + // also, when the lock bit of the next entry is set and the next entry is TOR, don't allow writes to this entry PMPADDR + assign CFGLocked[i] = PMPCFG_ARRAY_REGW[i][7]; + if (i == `PMP_ENTRIES-1) + assign ADDRLocked[i] = PMPCFG_ARRAY_REGW[i][7]; + else + assign ADDRLocked[i] = PMPCFG_ARRAY_REGW[i][7] | (PMPCFG_ARRAY_REGW[i+1][7] & PMPCFG_ARRAY_REGW[i+1][4:3] == 2'b01); + + assign WritePMPADDRM[i] = (CSRMWriteM & (CSRAdrM == (PMPADDR0+i))) & ~StallW & ~ADDRLocked[i]; + flopenr #(`XLEN) PMPADDRreg(clk, reset, WritePMPADDRM[i], CSRWriteValM, PMPADDR_ARRAY_REGW[i]); + if (`XLEN==64) begin + assign WritePMPCFGM[i] = (CSRMWriteM & (CSRAdrM == (PMPCFG0+2*(i/8)))) & ~StallW & ~CFGLocked[i]; + flopenr #(8) PMPCFGreg(clk, reset, WritePMPCFGM[i], CSRWriteValM[(i%8)*8+7:(i%8)*8], PMPCFG_ARRAY_REGW[i]); + end else begin + assign WritePMPCFGM[i] = (CSRMWriteM & (CSRAdrM == (PMPCFG0+i/4))) & ~StallW & ~CFGLocked[i]; + flopenr #(8) PMPCFGreg(clk, reset, WritePMPCFGM[i], CSRWriteValM[(i%4)*8+7:(i%4)*8], PMPCFG_ARRAY_REGW[i]); end end - endgenerate + end localparam MISA_26 = (`MISA) & 32'h03ffffff; @@ -143,28 +141,24 @@ module csrm #(parameter // CSRs flopenr #(`XLEN) MTVECreg(clk, reset, WriteMTVECM, {CSRWriteValM[`XLEN-1:2], 1'b0, CSRWriteValM[0]}, MTVEC_REGW); //busybear: changed reset value to 0 - generate - if (`S_SUPPORTED | (`U_SUPPORTED & `N_SUPPORTED)) begin:deleg // DELEG registers should exist - flopenr #(`XLEN) MEDELEGreg(clk, reset, WriteMEDELEGM, CSRWriteValM & MEDELEG_MASK /*12'h7FF*/, MEDELEG_REGW); - flopenr #(`XLEN) MIDELEGreg(clk, reset, WriteMIDELEGM, CSRWriteValM & MIDELEG_MASK /*12'h222*/, MIDELEG_REGW); - end else begin - assign MEDELEG_REGW = 0; - assign MIDELEG_REGW = 0; - end - endgenerate + if (`S_SUPPORTED | (`U_SUPPORTED & `N_SUPPORTED)) begin:deleg // DELEG registers should exist + flopenr #(`XLEN) MEDELEGreg(clk, reset, WriteMEDELEGM, CSRWriteValM & MEDELEG_MASK /*12'h7FF*/, MEDELEG_REGW); + flopenr #(`XLEN) MIDELEGreg(clk, reset, WriteMIDELEGM, CSRWriteValM & MIDELEG_MASK /*12'h222*/, MIDELEG_REGW); + end else begin + assign MEDELEG_REGW = 0; + assign MIDELEG_REGW = 0; + end flopenr #(`XLEN) MSCRATCHreg(clk, reset, WriteMSCRATCHM, CSRWriteValM, MSCRATCH_REGW); flopenr #(`XLEN) MEPCreg(clk, reset, WriteMEPCM, NextEPCM, MEPC_REGW); flopenr #(`XLEN) MCAUSEreg(clk, reset, WriteMCAUSEM, NextCauseM, MCAUSE_REGW); if(`QEMU) assign MTVAL_REGW = `XLEN'b0; else flopenr #(`XLEN) MTVALreg(clk, reset, WriteMTVALM, NextMtvalM, MTVAL_REGW); - generate // *** needs comment about bit 1 - if (`BUSYBEAR == 1) begin:counters + if (`BUSYBEAR == 1) begin:counters // counter 1 (TIME) enable tied to 0 to match simulator*** flopenr #(32) MCOUNTERENreg(clk, reset, WriteMCOUNTERENM, {CSRWriteValM[31:2],1'b0,CSRWriteValM[0]}, MCOUNTEREN_REGW); end else begin:counters flopenr #(32) MCOUNTERENreg(clk, reset, WriteMCOUNTERENM, CSRWriteValM[31:0], MCOUNTEREN_REGW); end - endgenerate flopenr #(32) MCOUNTINHIBITreg(clk, reset, WriteMCOUNTINHIBITM, CSRWriteValM[31:0], MCOUNTINHIBIT_REGW); diff --git a/pipelined/src/privileged/csrn.sv b/pipelined/src/privileged/csrn.sv index 17f4f4563..c20b7cf5a 100644 --- a/pipelined/src/privileged/csrn.sv +++ b/pipelined/src/privileged/csrn.sv @@ -49,52 +49,50 @@ module csrn #(parameter ); // User mode CSRs below only needed when user mode traps are supported - generate - if (`N_SUPPORTED) begin:nmode - logic WriteUTVECM; - logic WriteUSCRATCHM, WriteUEPCM; - logic WriteUCAUSEM, WriteUTVALM; - logic [`XLEN-1:0] UEDELEG_REGW, UIDELEG_REGW; - logic [`XLEN-1:0] USCRATCH_REGW, UCAUSE_REGW, UTVAL_REGW; - - // Write enables - assign WriteUSTATUSM = CSRNWriteM & (CSRAdrM == USTATUS) & ~StallW; - assign WriteUTVECM = CSRNWriteM & (CSRAdrM == UTVEC) & ~StallW; - assign WriteUEPCM = UTrapM | (CSRNWriteM & (CSRAdrM == UEPC)) & ~StallW; - assign WriteUCAUSEM = UTrapM | (CSRNWriteM & (CSRAdrM == UCAUSE)) & ~StallW; - assign WriteUTVALM = UTrapM | (CSRNWriteM & (CSRAdrM == UTVAL)) & ~StallW; + if (`N_SUPPORTED) begin:nmode // depricated; consider removing*** + logic WriteUTVECM; + logic WriteUSCRATCHM, WriteUEPCM; + logic WriteUCAUSEM, WriteUTVALM; + logic [`XLEN-1:0] UEDELEG_REGW, UIDELEG_REGW; + logic [`XLEN-1:0] USCRATCH_REGW, UCAUSE_REGW, UTVAL_REGW; + + // Write enables + assign WriteUSTATUSM = CSRNWriteM & (CSRAdrM == USTATUS) & ~StallW; + assign WriteUTVECM = CSRNWriteM & (CSRAdrM == UTVEC) & ~StallW; + assign WriteUEPCM = UTrapM | (CSRNWriteM & (CSRAdrM == UEPC)) & ~StallW; + assign WriteUCAUSEM = UTrapM | (CSRNWriteM & (CSRAdrM == UCAUSE)) & ~StallW; + assign WriteUTVALM = UTrapM | (CSRNWriteM & (CSRAdrM == UTVAL)) & ~StallW; - // CSRs - flopenl #(`XLEN) UTVECreg(clk, reset, WriteUTVECM, {CSRWriteValM[`XLEN-1:2], 1'b0, CSRWriteValM[0]}, `RESET_VECTOR, UTVEC_REGW); - flopenr #(`XLEN) USCRATCHreg(clk, reset, WriteUSCRATCHM, CSRWriteValM, USCRATCH_REGW); - flopenr #(`XLEN) UEPCreg(clk, reset, WriteUEPCM, NextEPCM, UEPC_REGW); - flopenr #(`XLEN) UCAUSEreg(clk, reset, WriteUCAUSEM, NextCauseM, UCAUSE_REGW); - flopenr #(`XLEN) UTVALreg(clk, reset, WriteUTVALM, NextMtvalM, UTVAL_REGW); + // CSRs + flopenl #(`XLEN) UTVECreg(clk, reset, WriteUTVECM, {CSRWriteValM[`XLEN-1:2], 1'b0, CSRWriteValM[0]}, `RESET_VECTOR, UTVEC_REGW); + flopenr #(`XLEN) USCRATCHreg(clk, reset, WriteUSCRATCHM, CSRWriteValM, USCRATCH_REGW); + flopenr #(`XLEN) UEPCreg(clk, reset, WriteUEPCM, NextEPCM, UEPC_REGW); + flopenr #(`XLEN) UCAUSEreg(clk, reset, WriteUCAUSEM, NextCauseM, UCAUSE_REGW); + flopenr #(`XLEN) UTVALreg(clk, reset, WriteUTVALM, NextMtvalM, UTVAL_REGW); - // CSR Reads - always_comb begin - IllegalCSRNAccessM = 0; - case (CSRAdrM) - USTATUS: CSRNReadValM = USTATUS_REGW; - UTVEC: CSRNReadValM = UTVEC_REGW; - UIP: CSRNReadValM = {{(`XLEN-12){1'b0}}, UIP_REGW}; - UIE: CSRNReadValM = {{(`XLEN-12){1'b0}}, UIE_REGW}; - USCRATCH: CSRNReadValM = USCRATCH_REGW; - UEPC: CSRNReadValM = UEPC_REGW; - UCAUSE: CSRNReadValM = UCAUSE_REGW; - UTVAL: CSRNReadValM = UTVAL_REGW; - default: begin - CSRNReadValM = 0; - IllegalCSRNAccessM = 1; - end - endcase - end - end else begin // if not supported - assign WriteUSTATUSM = 0; - assign CSRNReadValM = 0; - assign UEPC_REGW = 0; - assign UTVEC_REGW = 0; - assign IllegalCSRNAccessM = 1; + // CSR Reads + always_comb begin + IllegalCSRNAccessM = 0; + case (CSRAdrM) + USTATUS: CSRNReadValM = USTATUS_REGW; + UTVEC: CSRNReadValM = UTVEC_REGW; + UIP: CSRNReadValM = {{(`XLEN-12){1'b0}}, UIP_REGW}; + UIE: CSRNReadValM = {{(`XLEN-12){1'b0}}, UIE_REGW}; + USCRATCH: CSRNReadValM = USCRATCH_REGW; + UEPC: CSRNReadValM = UEPC_REGW; + UCAUSE: CSRNReadValM = UCAUSE_REGW; + UTVAL: CSRNReadValM = UTVAL_REGW; + default: begin + CSRNReadValM = 0; + IllegalCSRNAccessM = 1; + end + endcase end - endgenerate -endmodule + end else begin // if not supported + assign WriteUSTATUSM = 0; + assign CSRNReadValM = 0; + assign UEPC_REGW = 0; + assign UTVEC_REGW = 0; + assign IllegalCSRNAccessM = 1; + end + endmodule diff --git a/pipelined/src/privileged/csrs.sv b/pipelined/src/privileged/csrs.sv index daaafe639..413ee3c90 100644 --- a/pipelined/src/privileged/csrs.sv +++ b/pipelined/src/privileged/csrs.sv @@ -69,89 +69,87 @@ module csrs #(parameter //logic [`XLEN-1:0] SEDELEG_MASK = ~(zero | 3'b111 << 9); // sedeleg[11:9] hardwired to zero per Privileged Spec 3.1.8 // Supervisor mode CSRs sometimes supported - generate - if (`S_SUPPORTED) begin:csrs - logic WriteSTVECM; - logic WriteSSCRATCHM, WriteSEPCM; - logic WriteSCAUSEM, WriteSTVALM, WriteSATPM, WriteSCOUNTERENM; - logic [`XLEN-1:0] SSCRATCH_REGW, STVAL_REGW; - (* mark_debug = "true" *) logic [`XLEN-1:0] SCAUSE_REGW; - - assign WriteSSTATUSM = CSRSWriteM & (CSRAdrM == SSTATUS) & ~StallW; - assign WriteSTVECM = CSRSWriteM & (CSRAdrM == STVEC) & ~StallW; - assign WriteSSCRATCHM = CSRSWriteM & (CSRAdrM == SSCRATCH) & ~StallW; - assign WriteSEPCM = STrapM | (CSRSWriteM & (CSRAdrM == SEPC)) & ~StallW; - assign WriteSCAUSEM = STrapM | (CSRSWriteM & (CSRAdrM == SCAUSE)) & ~StallW; - assign WriteSTVALM = STrapM | (CSRSWriteM & (CSRAdrM == STVAL)) & ~StallW; - assign WriteSATPM = CSRSWriteM & (CSRAdrM == SATP) & (PrivilegeModeW == `M_MODE | ~STATUS_TVM) & ~StallW; - assign WriteSCOUNTERENM = CSRSWriteM & (CSRAdrM == SCOUNTEREN) & ~StallW; + if (`S_SUPPORTED) begin:csrs + logic WriteSTVECM; + logic WriteSSCRATCHM, WriteSEPCM; + logic WriteSCAUSEM, WriteSTVALM, WriteSATPM, WriteSCOUNTERENM; + logic [`XLEN-1:0] SSCRATCH_REGW, STVAL_REGW; + (* mark_debug = "true" *) logic [`XLEN-1:0] SCAUSE_REGW; + + assign WriteSSTATUSM = CSRSWriteM & (CSRAdrM == SSTATUS) & ~StallW; + assign WriteSTVECM = CSRSWriteM & (CSRAdrM == STVEC) & ~StallW; + assign WriteSSCRATCHM = CSRSWriteM & (CSRAdrM == SSCRATCH) & ~StallW; + assign WriteSEPCM = STrapM | (CSRSWriteM & (CSRAdrM == SEPC)) & ~StallW; + assign WriteSCAUSEM = STrapM | (CSRSWriteM & (CSRAdrM == SCAUSE)) & ~StallW; + assign WriteSTVALM = STrapM | (CSRSWriteM & (CSRAdrM == STVAL)) & ~StallW; + assign WriteSATPM = CSRSWriteM & (CSRAdrM == SATP) & (PrivilegeModeW == `M_MODE | ~STATUS_TVM) & ~StallW; + assign WriteSCOUNTERENM = CSRSWriteM & (CSRAdrM == SCOUNTEREN) & ~StallW; - // CSRs - flopenr #(`XLEN) STVECreg(clk, reset, WriteSTVECM, {CSRWriteValM[`XLEN-1:2], 1'b0, CSRWriteValM[0]}, STVEC_REGW); //busybear: change reset to 0 - flopenr #(`XLEN) SSCRATCHreg(clk, reset, WriteSSCRATCHM, CSRWriteValM, SSCRATCH_REGW); - flopenr #(`XLEN) SEPCreg(clk, reset, WriteSEPCM, NextEPCM, SEPC_REGW); - flopenr #(`XLEN) SCAUSEreg(clk, reset, WriteSCAUSEM, NextCauseM, SCAUSE_REGW); - flopenr #(`XLEN) STVALreg(clk, reset, WriteSTVALM, NextMtvalM, STVAL_REGW); - if (`MEM_VIRTMEM) - flopenr #(`XLEN) SATPreg(clk, reset, WriteSATPM, CSRWriteValM, SATP_REGW); - else - assign SATP_REGW = 0; // hardwire to zero if virtual memory not supported - if (`BUSYBEAR == 1) begin:scounteren - flopenr #(32) SCOUNTERENreg(clk, reset, WriteSCOUNTERENM, {CSRWriteValM[31:2],1'b0,CSRWriteValM[0]}, SCOUNTEREN_REGW); - end else if (`BUILDROOT == 1) begin:scounteren - flopenr #(32) SCOUNTERENreg(clk, reset, WriteSCOUNTERENM, CSRWriteValM[31:0], SCOUNTEREN_REGW); - end else begin:scounteren - flopens #(32) SCOUNTERENreg(clk, reset, WriteSCOUNTERENM, CSRWriteValM[31:0], SCOUNTEREN_REGW); - end - if (`N_SUPPORTED) begin:nregs - logic WriteSEDELEGM, WriteSIDELEGM; - assign WriteSEDELEGM = CSRSWriteM & (CSRAdrM == SEDELEG); - assign WriteSIDELEGM = CSRSWriteM & (CSRAdrM == SIDELEG); - flopenr #(`XLEN) SEDELEGreg(clk, reset, WriteSEDELEGM, CSRWriteValM & SEDELEG_MASK, SEDELEG_REGW); - flopenr #(`XLEN) SIDELEGreg(clk, reset, WriteSIDELEGM, CSRWriteValM, SIDELEG_REGW); - end else begin - assign SEDELEG_REGW = 0; - assign SIDELEG_REGW = 0; - end - - // CSR Reads - always_comb begin:csrr - IllegalCSRSAccessM = !(`N_SUPPORTED) & (CSRAdrM == SEDELEG | CSRAdrM == SIDELEG); // trap on DELEG register access when no N-mode - case (CSRAdrM) - SSTATUS: CSRSReadValM = SSTATUS_REGW; - STVEC: CSRSReadValM = STVEC_REGW; -// SIDELEG: CSRSReadValM = {{(`XLEN-12){1'b0}}, SIDELEG_REGW}; -// SEDELEG: CSRSReadValM = {{(`XLEN-12){1'b0}}, SEDELEG_REGW}; - SIDELEG: CSRSReadValM = SIDELEG_REGW; - SEDELEG: CSRSReadValM = SEDELEG_REGW; - SIP: CSRSReadValM = {{(`XLEN-12){1'b0}}, SIP_REGW}; - SIE: CSRSReadValM = {{(`XLEN-12){1'b0}}, SIE_REGW}; - SSCRATCH: CSRSReadValM = SSCRATCH_REGW; - SEPC: CSRSReadValM = SEPC_REGW; - SCAUSE: CSRSReadValM = SCAUSE_REGW; - STVAL: CSRSReadValM = STVAL_REGW; - SATP: if (`MEM_VIRTMEM & (PrivilegeModeW == `M_MODE | ~STATUS_TVM)) CSRSReadValM = SATP_REGW; - else begin - CSRSReadValM = 0; - if (PrivilegeModeW == `S_MODE & STATUS_TVM) IllegalCSRSAccessM = 1; - end - SCOUNTEREN:CSRSReadValM = {{(`XLEN-32){1'b0}}, SCOUNTEREN_REGW}; - default: begin - CSRSReadValM = 0; - IllegalCSRSAccessM = 1; - end - endcase - end + // CSRs + flopenr #(`XLEN) STVECreg(clk, reset, WriteSTVECM, {CSRWriteValM[`XLEN-1:2], 1'b0, CSRWriteValM[0]}, STVEC_REGW); //busybear: change reset to 0 + flopenr #(`XLEN) SSCRATCHreg(clk, reset, WriteSSCRATCHM, CSRWriteValM, SSCRATCH_REGW); + flopenr #(`XLEN) SEPCreg(clk, reset, WriteSEPCM, NextEPCM, SEPC_REGW); + flopenr #(`XLEN) SCAUSEreg(clk, reset, WriteSCAUSEM, NextCauseM, SCAUSE_REGW); + flopenr #(`XLEN) STVALreg(clk, reset, WriteSTVALM, NextMtvalM, STVAL_REGW); + if (`MEM_VIRTMEM) + flopenr #(`XLEN) SATPreg(clk, reset, WriteSATPM, CSRWriteValM, SATP_REGW); + else + assign SATP_REGW = 0; // hardwire to zero if virtual memory not supported + if (`BUSYBEAR == 1) begin:scounteren + flopenr #(32) SCOUNTERENreg(clk, reset, WriteSCOUNTERENM, {CSRWriteValM[31:2],1'b0,CSRWriteValM[0]}, SCOUNTEREN_REGW); + end else if (`BUILDROOT == 1) begin:scounteren + flopenr #(32) SCOUNTERENreg(clk, reset, WriteSCOUNTERENM, CSRWriteValM[31:0], SCOUNTEREN_REGW); + end else begin:scounteren + flopens #(32) SCOUNTERENreg(clk, reset, WriteSCOUNTERENM, CSRWriteValM[31:0], SCOUNTEREN_REGW); + end + if (`N_SUPPORTED) begin:nregs + logic WriteSEDELEGM, WriteSIDELEGM; + assign WriteSEDELEGM = CSRSWriteM & (CSRAdrM == SEDELEG); + assign WriteSIDELEGM = CSRSWriteM & (CSRAdrM == SIDELEG); + flopenr #(`XLEN) SEDELEGreg(clk, reset, WriteSEDELEGM, CSRWriteValM & SEDELEG_MASK, SEDELEG_REGW); + flopenr #(`XLEN) SIDELEGreg(clk, reset, WriteSIDELEGM, CSRWriteValM, SIDELEG_REGW); end else begin - assign WriteSSTATUSM = 0; - assign CSRSReadValM = 0; - assign SEPC_REGW = 0; - assign STVEC_REGW = 0; assign SEDELEG_REGW = 0; assign SIDELEG_REGW = 0; - assign SCOUNTEREN_REGW = 0; - assign SATP_REGW = 0; - assign IllegalCSRSAccessM = 1; end - endgenerate + + // CSR Reads + always_comb begin:csrr + IllegalCSRSAccessM = !(`N_SUPPORTED) & (CSRAdrM == SEDELEG | CSRAdrM == SIDELEG); // trap on DELEG register access when no N-mode + case (CSRAdrM) + SSTATUS: CSRSReadValM = SSTATUS_REGW; + STVEC: CSRSReadValM = STVEC_REGW; +// SIDELEG: CSRSReadValM = {{(`XLEN-12){1'b0}}, SIDELEG_REGW}; +// SEDELEG: CSRSReadValM = {{(`XLEN-12){1'b0}}, SEDELEG_REGW}; + SIDELEG: CSRSReadValM = SIDELEG_REGW; + SEDELEG: CSRSReadValM = SEDELEG_REGW; + SIP: CSRSReadValM = {{(`XLEN-12){1'b0}}, SIP_REGW}; + SIE: CSRSReadValM = {{(`XLEN-12){1'b0}}, SIE_REGW}; + SSCRATCH: CSRSReadValM = SSCRATCH_REGW; + SEPC: CSRSReadValM = SEPC_REGW; + SCAUSE: CSRSReadValM = SCAUSE_REGW; + STVAL: CSRSReadValM = STVAL_REGW; + SATP: if (`MEM_VIRTMEM & (PrivilegeModeW == `M_MODE | ~STATUS_TVM)) CSRSReadValM = SATP_REGW; + else begin + CSRSReadValM = 0; + if (PrivilegeModeW == `S_MODE & STATUS_TVM) IllegalCSRSAccessM = 1; + end + SCOUNTEREN:CSRSReadValM = {{(`XLEN-32){1'b0}}, SCOUNTEREN_REGW}; + default: begin + CSRSReadValM = 0; + IllegalCSRSAccessM = 1; + end + endcase + end + end else begin + assign WriteSSTATUSM = 0; + assign CSRSReadValM = 0; + assign SEPC_REGW = 0; + assign STVEC_REGW = 0; + assign SEDELEG_REGW = 0; + assign SIDELEG_REGW = 0; + assign SCOUNTEREN_REGW = 0; + assign SATP_REGW = 0; + assign IllegalCSRSAccessM = 1; + end endmodule diff --git a/pipelined/src/privileged/csrsr.sv b/pipelined/src/privileged/csrsr.sv index 3b14fd59c..85d164683 100644 --- a/pipelined/src/privileged/csrsr.sv +++ b/pipelined/src/privileged/csrsr.sv @@ -50,54 +50,50 @@ module csrsr ( // See Privileged Spec Section 3.1.6 // Lower privilege status registers are a subset of the full status register // *** consider adding MBE, SBE, UBE fields later from 20210108 draft spec - generate - if (`XLEN==64) begin: csrsr64 // RV64 - assign MSTATUS_REGW = {STATUS_SD, 27'b0, STATUS_SXL, STATUS_UXL, 9'b0, - STATUS_TSR, STATUS_TW, STATUS_TVM, STATUS_MXR, STATUS_SUM, STATUS_MPRV, - STATUS_XS, STATUS_FS, STATUS_MPP, 2'b0, - STATUS_SPP, STATUS_MPIE, 1'b0, STATUS_SPIE, STATUS_UPIE, - STATUS_MIE, 1'b0, STATUS_SIE, STATUS_UIE}; - assign SSTATUS_REGW = {STATUS_SD, /*27'b0, */ 29'b0, /*STATUS_SXL, */ STATUS_UXL, /*9'b0, */ 12'b0, - /*STATUS_TSR, STATUS_TW, STATUS_TVM, */STATUS_MXR, STATUS_SUM, /* STATUS_MPRV, */ 1'b0, - STATUS_XS, STATUS_FS, /*STATUS_MPP, 2'b0*/ 4'b0, - STATUS_SPP, /*STATUS_MPIE, 1'b0*/ 2'b0, STATUS_SPIE, STATUS_UPIE, - /*STATUS_MIE, 1'b0*/ 2'b0, STATUS_SIE, STATUS_UIE}; - assign USTATUS_REGW = {/*STATUS_SD, */ 59'b0, /*STATUS_SXL, STATUS_UXL, 9'b0, */ - /*STATUS_TSR, STATUS_TW, STATUS_TVM, STATUS_MXR, STATUS_SUM, STATUS_MPRV, , 1'b0,*/ - /* STATUS_XS, STATUS_FS, /*STATUS_MPP, 8'b0, */ - /*STATUS_SPP, STATUS_MPIE, 1'b0 2'b0, STATUS_SPIE,*/ STATUS_UPIE, - /*STATUS_MIE, 1'b0*/ 3'b0, /*STATUS_SIE, */STATUS_UIE}; - end else begin: csrsr32 // RV32 - assign MSTATUS_REGW = {STATUS_SD, 8'b0, - STATUS_TSR, STATUS_TW, STATUS_TVM, STATUS_MXR, STATUS_SUM, STATUS_MPRV, - STATUS_XS, STATUS_FS, STATUS_MPP, 2'b0, - STATUS_SPP, STATUS_MPIE, 1'b0, STATUS_SPIE, STATUS_UPIE, STATUS_MIE, 1'b0, STATUS_SIE, STATUS_UIE}; - assign SSTATUS_REGW = {STATUS_SD, 11'b0, - /*STATUS_TSR, STATUS_TW, STATUS_TVM, */STATUS_MXR, STATUS_SUM, /* STATUS_MPRV, */ 1'b0, - STATUS_XS, STATUS_FS, /*STATUS_MPP, 2'b0*/ 4'b0, - STATUS_SPP, /*STATUS_MPIE, 1'b0*/ 2'b0, STATUS_SPIE, STATUS_UPIE, - /*STATUS_MIE, 1'b0*/ 2'b0, STATUS_SIE, STATUS_UIE}; - assign USTATUS_REGW = {/*STATUS_SD, */ 27'b0, /*STATUS_SXL, STATUS_UXL, 9'b0, */ - /*STATUS_TSR, STATUS_TW, STATUS_TVM, STATUS_MXR, STATUS_SUM, STATUS_MPRV, , 1'b0,*/ - /*STATUS_XS, STATUS_FS, STATUS_MPP, 8'b0, */ - /*STATUS_SPP, STATUS_MPIE, 1'b0 2'b0, STATUS_SPIE,*/ STATUS_UPIE, - /*STATUS_MIE, 1'b0*/ 3'b0, /*STATUS_SIE, */STATUS_UIE}; - end - endgenerate + if (`XLEN==64) begin: csrsr64 // RV64 + assign MSTATUS_REGW = {STATUS_SD, 27'b0, STATUS_SXL, STATUS_UXL, 9'b0, + STATUS_TSR, STATUS_TW, STATUS_TVM, STATUS_MXR, STATUS_SUM, STATUS_MPRV, + STATUS_XS, STATUS_FS, STATUS_MPP, 2'b0, + STATUS_SPP, STATUS_MPIE, 1'b0, STATUS_SPIE, STATUS_UPIE, + STATUS_MIE, 1'b0, STATUS_SIE, STATUS_UIE}; + assign SSTATUS_REGW = {STATUS_SD, /*27'b0, */ 29'b0, /*STATUS_SXL, */ STATUS_UXL, /*9'b0, */ 12'b0, + /*STATUS_TSR, STATUS_TW, STATUS_TVM, */STATUS_MXR, STATUS_SUM, /* STATUS_MPRV, */ 1'b0, + STATUS_XS, STATUS_FS, /*STATUS_MPP, 2'b0*/ 4'b0, + STATUS_SPP, /*STATUS_MPIE, 1'b0*/ 2'b0, STATUS_SPIE, STATUS_UPIE, + /*STATUS_MIE, 1'b0*/ 2'b0, STATUS_SIE, STATUS_UIE}; + assign USTATUS_REGW = {/*STATUS_SD, */ 59'b0, /*STATUS_SXL, STATUS_UXL, 9'b0, */ + /*STATUS_TSR, STATUS_TW, STATUS_TVM, STATUS_MXR, STATUS_SUM, STATUS_MPRV, , 1'b0,*/ + /* STATUS_XS, STATUS_FS, /*STATUS_MPP, 8'b0, */ + /*STATUS_SPP, STATUS_MPIE, 1'b0 2'b0, STATUS_SPIE,*/ STATUS_UPIE, + /*STATUS_MIE, 1'b0*/ 3'b0, /*STATUS_SIE, */STATUS_UIE}; + end else begin: csrsr32 // RV32 + assign MSTATUS_REGW = {STATUS_SD, 8'b0, + STATUS_TSR, STATUS_TW, STATUS_TVM, STATUS_MXR, STATUS_SUM, STATUS_MPRV, + STATUS_XS, STATUS_FS, STATUS_MPP, 2'b0, + STATUS_SPP, STATUS_MPIE, 1'b0, STATUS_SPIE, STATUS_UPIE, STATUS_MIE, 1'b0, STATUS_SIE, STATUS_UIE}; + assign SSTATUS_REGW = {STATUS_SD, 11'b0, + /*STATUS_TSR, STATUS_TW, STATUS_TVM, */STATUS_MXR, STATUS_SUM, /* STATUS_MPRV, */ 1'b0, + STATUS_XS, STATUS_FS, /*STATUS_MPP, 2'b0*/ 4'b0, + STATUS_SPP, /*STATUS_MPIE, 1'b0*/ 2'b0, STATUS_SPIE, STATUS_UPIE, + /*STATUS_MIE, 1'b0*/ 2'b0, STATUS_SIE, STATUS_UIE}; + assign USTATUS_REGW = {/*STATUS_SD, */ 27'b0, /*STATUS_SXL, STATUS_UXL, 9'b0, */ + /*STATUS_TSR, STATUS_TW, STATUS_TVM, STATUS_MXR, STATUS_SUM, STATUS_MPRV, , 1'b0,*/ + /*STATUS_XS, STATUS_FS, STATUS_MPP, 8'b0, */ + /*STATUS_SPP, STATUS_MPIE, 1'b0 2'b0, STATUS_SPIE,*/ STATUS_UPIE, + /*STATUS_MIE, 1'b0*/ 3'b0, /*STATUS_SIE, */STATUS_UIE}; + end // harwired STATUS bits - generate - assign STATUS_TSR = `S_SUPPORTED & STATUS_TSR_INT; // override reigster with 0 if supervisor mode not supported - assign STATUS_TW = (`S_SUPPORTED | `U_SUPPORTED) & STATUS_TW_INT; // override reigster with 0 if only machine mode supported - assign STATUS_TVM = `S_SUPPORTED & STATUS_TVM_INT; // override reigster with 0 if supervisor mode not supported - assign STATUS_MXR = `S_SUPPORTED & STATUS_MXR_INT; // override reigster with 0 if supervisor mode not supported - // SXL and UXL bits only matter for RV64. Set to 10 for RV64 if mode is supported, or 0 if not - assign STATUS_SXL = `S_SUPPORTED & ~`QEMU ? 2'b10 : 2'b00; // 10 if supervisor mode supported - assign STATUS_UXL = `U_SUPPORTED & ~`QEMU ? 2'b10 : 2'b00; // 10 if user mode supported - assign STATUS_SUM = `S_SUPPORTED & `MEM_VIRTMEM & STATUS_SUM_INT; // override reigster with 0 if supervisor mode not supported - assign STATUS_MPRV = `U_SUPPORTED & STATUS_MPRV_INT; // override with 0 if user mode not supported - assign STATUS_FS = (`S_SUPPORTED & (`F_SUPPORTED | `D_SUPPORTED)) ? STATUS_FS_INT : 2'b00; // off if no FP - endgenerate + assign STATUS_TSR = `S_SUPPORTED & STATUS_TSR_INT; // override reigster with 0 if supervisor mode not supported + assign STATUS_TW = (`S_SUPPORTED | `U_SUPPORTED) & STATUS_TW_INT; // override reigster with 0 if only machine mode supported + assign STATUS_TVM = `S_SUPPORTED & STATUS_TVM_INT; // override reigster with 0 if supervisor mode not supported + assign STATUS_MXR = `S_SUPPORTED & STATUS_MXR_INT; // override reigster with 0 if supervisor mode not supported + // SXL and UXL bits only matter for RV64. Set to 10 for RV64 if mode is supported, or 0 if not + assign STATUS_SXL = `S_SUPPORTED & ~`QEMU ? 2'b10 : 2'b00; // 10 if supervisor mode supported + assign STATUS_UXL = `U_SUPPORTED & ~`QEMU ? 2'b10 : 2'b00; // 10 if user mode supported + assign STATUS_SUM = `S_SUPPORTED & `MEM_VIRTMEM & STATUS_SUM_INT; // override reigster with 0 if supervisor mode not supported + assign STATUS_MPRV = `U_SUPPORTED & STATUS_MPRV_INT; // override with 0 if user mode not supported + assign STATUS_FS = (`S_SUPPORTED & (`F_SUPPORTED | `D_SUPPORTED)) ? STATUS_FS_INT : 2'b00; // off if no FP assign STATUS_SD = (STATUS_FS == 2'b11) | (STATUS_XS == 2'b11); // dirty state logic assign STATUS_XS = 2'b00; // No additional user-mode state to be dirty diff --git a/pipelined/src/privileged/csru.sv b/pipelined/src/privileged/csru.sv index d92a50cb9..eb5e53995 100644 --- a/pipelined/src/privileged/csru.sv +++ b/pipelined/src/privileged/csru.sv @@ -44,42 +44,40 @@ module csru #(parameter ); // Floating Point CSRs in User Mode only needed if Floating Point is supported - generate - if (`F_SUPPORTED | `D_SUPPORTED) begin:csru - logic [4:0] FFLAGS_REGW; - logic [2:0] NextFRMM; - logic [4:0] NextFFLAGSM; - - // Write enables - //assign WriteFCSRM = CSRUWriteM & (CSRAdrM == FCSR) & ~StallW; - assign WriteFRMM = (CSRUWriteM & (CSRAdrM == FRM | CSRAdrM == FCSR)) & ~StallW; - assign WriteFFLAGSM = (CSRUWriteM & (CSRAdrM == FFLAGS | CSRAdrM == FCSR)) & ~StallW; - - // Write Values - assign NextFRMM = (CSRAdrM == FCSR) ? CSRWriteValM[7:5] : CSRWriteValM[2:0]; - assign NextFFLAGSM = WriteFFLAGSM ? CSRWriteValM[4:0] : FFLAGS_REGW | SetFflagsM; + if (`F_SUPPORTED | `D_SUPPORTED) begin:csru + logic [4:0] FFLAGS_REGW; + logic [2:0] NextFRMM; + logic [4:0] NextFFLAGSM; + + // Write enables + //assign WriteFCSRM = CSRUWriteM & (CSRAdrM == FCSR) & ~StallW; + assign WriteFRMM = (CSRUWriteM & (CSRAdrM == FRM | CSRAdrM == FCSR)) & ~StallW; + assign WriteFFLAGSM = (CSRUWriteM & (CSRAdrM == FFLAGS | CSRAdrM == FCSR)) & ~StallW; + + // Write Values + assign NextFRMM = (CSRAdrM == FCSR) ? CSRWriteValM[7:5] : CSRWriteValM[2:0]; + assign NextFFLAGSM = WriteFFLAGSM ? CSRWriteValM[4:0] : FFLAGS_REGW | SetFflagsM; - // CSRs - flopenr #(3) FRMreg(clk, reset, WriteFRMM, NextFRMM, FRM_REGW); - flopr #(5) FFLAGSreg(clk, reset, NextFFLAGSM, FFLAGS_REGW); + // CSRs + flopenr #(3) FRMreg(clk, reset, WriteFRMM, NextFRMM, FRM_REGW); + flopr #(5) FFLAGSreg(clk, reset, NextFFLAGSM, FFLAGS_REGW); - // CSR Reads - always_comb begin - IllegalCSRUAccessM = 0; - case (CSRAdrM) - FFLAGS: CSRUReadValM = {{(`XLEN-5){1'b0}}, FFLAGS_REGW}; - FRM: CSRUReadValM = {{(`XLEN-3){1'b0}}, FRM_REGW}; - FCSR: CSRUReadValM = {{(`XLEN-8){1'b0}}, FRM_REGW, FFLAGS_REGW}; - default: begin - CSRUReadValM = 0; - IllegalCSRUAccessM = 1; - end - endcase - end - end else begin // if not supported - assign FRM_REGW = 0; - assign CSRUReadValM = 0; - assign IllegalCSRUAccessM = 1; + // CSR Reads + always_comb begin + IllegalCSRUAccessM = 0; + case (CSRAdrM) + FFLAGS: CSRUReadValM = {{(`XLEN-5){1'b0}}, FFLAGS_REGW}; + FRM: CSRUReadValM = {{(`XLEN-3){1'b0}}, FRM_REGW}; + FCSR: CSRUReadValM = {{(`XLEN-8){1'b0}}, FRM_REGW, FFLAGS_REGW}; + default: begin + CSRUReadValM = 0; + IllegalCSRUAccessM = 1; + end + endcase end - endgenerate + end else begin // if not supported + assign FRM_REGW = 0; + assign CSRUReadValM = 0; + assign IllegalCSRUAccessM = 1; + end endmodule diff --git a/pipelined/src/privileged/trap.sv b/pipelined/src/privileged/trap.sv index f48a8ad09..3fac49ff8 100644 --- a/pipelined/src/privileged/trap.sv +++ b/pipelined/src/privileged/trap.sv @@ -103,18 +103,16 @@ module trap ( // > implemented without a hardware adder circuit. // For example, we could require m/stvec be aligned on 7 bits to let us replace the adder directly below with // [untested] PrivilegedVectoredTrapVector = {PrivilegedTrapVector[`XLEN-1:7], CauseM[3:0], 4'b0000} - generate - if(`VECTORED_INTERRUPTS_SUPPORTED) begin:vec - always_comb - if (PrivilegedTrapVector[1:0] == 2'b01 & CauseM[`XLEN-1] == 1) - PrivilegedVectoredTrapVector = {PrivilegedTrapVector[`XLEN-1:2] + {CauseM[`XLEN-5:0], 2'b00}, 2'b00}; - else - PrivilegedVectoredTrapVector = {PrivilegedTrapVector[`XLEN-1:2], 2'b00}; - end - else begin - assign PrivilegedVectoredTrapVector = {PrivilegedTrapVector[`XLEN-1:2], 2'b00}; - end - endgenerate + if(`VECTORED_INTERRUPTS_SUPPORTED) begin:vec + always_comb + if (PrivilegedTrapVector[1:0] == 2'b01 & CauseM[`XLEN-1] == 1) + PrivilegedVectoredTrapVector = {PrivilegedTrapVector[`XLEN-1:2] + {CauseM[`XLEN-5:0], 2'b00}, 2'b00}; + else + PrivilegedVectoredTrapVector = {PrivilegedTrapVector[`XLEN-1:2], 2'b00}; + end + else begin + assign PrivilegedVectoredTrapVector = {PrivilegedTrapVector[`XLEN-1:2], 2'b00}; + end always_comb if (mretM) PrivilegedNextPCM = MEPC_REGW; diff --git a/pipelined/src/uncore/clint.sv b/pipelined/src/uncore/clint.sv index 3f0d61e44..bcc8a01c7 100644 --- a/pipelined/src/uncore/clint.sv +++ b/pipelined/src/uncore/clint.sv @@ -55,12 +55,8 @@ module clint ( assign HREADYCLINT = 1'b1; // *** needs to depend on DONE during accesses // word aligned reads - generate - if (`XLEN==64) - assign #2 entry = {HADDR[15:3], 3'b000}; - else - assign #2 entry = {HADDR[15:2], 2'b00}; - endgenerate + if (`XLEN==64) assign #2 entry = {HADDR[15:3], 3'b000}; + else assign #2 entry = {HADDR[15:2], 2'b00}; // DH 2/20/21: Eventually allow MTIME to run off a separate clock // This will require synchronizing MTIME to the system clock @@ -69,74 +65,72 @@ module clint ( // Use req and ack signals synchronized across the clock domains. // register access - generate - if (`XLEN==64) begin:clint // 64-bit - always @(posedge HCLK) begin - case(entry) - 16'h0000: HREADCLINT <= {63'b0, MSIP}; - 16'h4000: HREADCLINT <= MTIMECMP; - 16'hBFF8: HREADCLINT <= MTIME; - default: HREADCLINT <= 0; - endcase - end - always_ff @(posedge HCLK or negedge HRESETn) - if (~HRESETn) begin - MSIP <= 0; - MTIMECMP <= 0; - // MTIMECMP is not reset - end else if (memwrite) begin - if (entryd == 16'h0000) MSIP <= HWDATA[0]; - if (entryd == 16'h4000) MTIMECMP <= HWDATA; - end - - // eventually replace MTIME logic below with timereg - // timereg tr(HCLK, HRESETn, TIMECLK, memwrite & (entryd==16'hBFF8), 1'b0, HWDATA, MTIME, done); - - always_ff @(posedge HCLK or negedge HRESETn) - if (~HRESETn) begin - MTIME <= 0; - // MTIMECMP is not reset - end else if (memwrite & entryd == 16'hBFF8) begin - // MTIME Counter. Eventually change this to run off separate clock. Synchronization then needed - MTIME <= HWDATA; - end else MTIME <= MTIME + 1; - end else begin:clint // 32-bit - always @(posedge HCLK) begin - case(entry) - 16'h0000: HREADCLINT <= {31'b0, MSIP}; - 16'h4000: HREADCLINT <= MTIMECMP[31:0]; - 16'h4004: HREADCLINT <= MTIMECMP[63:32]; - 16'hBFF8: HREADCLINT <= MTIME[31:0]; - 16'hBFFC: HREADCLINT <= MTIME[63:32]; - default: HREADCLINT <= 0; - endcase - end - always_ff @(posedge HCLK or negedge HRESETn) - if (~HRESETn) begin - MSIP <= 0; - MTIMECMP <= 0; - // MTIMECMP is not reset ***? - end else if (memwrite) begin - if (entryd == 16'h0000) MSIP <= HWDATA[0]; - if (entryd == 16'h4000) MTIMECMP[31:0] <= HWDATA; - if (entryd == 16'h4004) MTIMECMP[63:32] <= HWDATA; - // MTIME Counter. Eventually change this to run off separate clock. Synchronization then needed - end + if (`XLEN==64) begin:clint // 64-bit + always @(posedge HCLK) begin + case(entry) + 16'h0000: HREADCLINT <= {63'b0, MSIP}; + 16'h4000: HREADCLINT <= MTIMECMP; + 16'hBFF8: HREADCLINT <= MTIME; + default: HREADCLINT <= 0; + endcase + end + always_ff @(posedge HCLK or negedge HRESETn) + if (~HRESETn) begin + MSIP <= 0; + MTIMECMP <= 0; + // MTIMECMP is not reset + end else if (memwrite) begin + if (entryd == 16'h0000) MSIP <= HWDATA[0]; + if (entryd == 16'h4000) MTIMECMP <= HWDATA; + end // eventually replace MTIME logic below with timereg - // timereg tr(HCLK, HRESETn, TIMECLK, memwrite & (entryd==16'hBFF8), memwrite & (entryd == 16'hBFFC), HWDATA, MTIME, done); - always_ff @(posedge HCLK or negedge HRESETn) - if (~HRESETn) begin - MTIME <= 0; - // MTIMECMP is not reset - end else if (memwrite & (entryd == 16'hBFF8)) begin - MTIME[31:0] <= HWDATA; - end else if (memwrite & (entryd == 16'hBFFC)) begin - // MTIME Counter. Eventually change this to run off separate clock. Synchronization then needed - MTIME[63:32]<= HWDATA; - end else MTIME <= MTIME + 1; +// timereg tr(HCLK, HRESETn, TIMECLK, memwrite & (entryd==16'hBFF8), 1'b0, HWDATA, MTIME, done); + + always_ff @(posedge HCLK or negedge HRESETn) + if (~HRESETn) begin + MTIME <= 0; + // MTIMECMP is not reset + end else if (memwrite & entryd == 16'hBFF8) begin + // MTIME Counter. Eventually change this to run off separate clock. Synchronization then needed + MTIME <= HWDATA; + end else MTIME <= MTIME + 1; + end else begin:clint // 32-bit + always @(posedge HCLK) begin + case(entry) + 16'h0000: HREADCLINT <= {31'b0, MSIP}; + 16'h4000: HREADCLINT <= MTIMECMP[31:0]; + 16'h4004: HREADCLINT <= MTIMECMP[63:32]; + 16'hBFF8: HREADCLINT <= MTIME[31:0]; + 16'hBFFC: HREADCLINT <= MTIME[63:32]; + default: HREADCLINT <= 0; + endcase end - endgenerate + always_ff @(posedge HCLK or negedge HRESETn) + if (~HRESETn) begin + MSIP <= 0; + MTIMECMP <= 0; + // MTIMECMP is not reset ***? + end else if (memwrite) begin + if (entryd == 16'h0000) MSIP <= HWDATA[0]; + if (entryd == 16'h4000) MTIMECMP[31:0] <= HWDATA; + if (entryd == 16'h4004) MTIMECMP[63:32] <= HWDATA; + // MTIME Counter. Eventually change this to run off separate clock. Synchronization then needed + end + +// eventually replace MTIME logic below with timereg +// timereg tr(HCLK, HRESETn, TIMECLK, memwrite & (entryd==16'hBFF8), memwrite & (entryd == 16'hBFFC), HWDATA, MTIME, done); + always_ff @(posedge HCLK or negedge HRESETn) + if (~HRESETn) begin + MTIME <= 0; + // MTIMECMP is not reset + end else if (memwrite & (entryd == 16'hBFF8)) begin + MTIME[31:0] <= HWDATA; + end else if (memwrite & (entryd == 16'hBFFC)) begin + // MTIME Counter. Eventually change this to run off separate clock. Synchronization then needed + MTIME[63:32]<= HWDATA; + end else MTIME <= MTIME + 1; + end // Software interrupt when MSIP is set assign SwIntM = MSIP; @@ -234,13 +228,9 @@ module graytobinary #(parameter N = `XLEN) ( // B[N-1] = G[N-1]; B[i] = G[i] ^ B[i+1] for 0 <= i < N-1 // requires rippling through N-1 XOR gates - generate - begin - genvar i; - assign b[N-1] = g[N-1]; - for (i=N-2; i >= 0; i--) begin:g2b - assign b[i] = g[i] ^ b[i+1]; - end + genvar i; + assign b[N-1] = g[N-1]; + for (i=N-2; i >= 0; i--) begin:g2b + assign b[i] = g[i] ^ b[i+1]; end - endgenerate endmodule diff --git a/pipelined/src/uncore/gpio.sv b/pipelined/src/uncore/gpio.sv index c5a62eaae..35e236a79 100644 --- a/pipelined/src/uncore/gpio.sv +++ b/pipelined/src/uncore/gpio.sv @@ -61,23 +61,13 @@ module gpio ( // account for subword read/write circuitry // -- Note GPIO registers are 32 bits no matter what; access them with LW SW. // (At least that's what I think when FE310 spec says "only naturally aligned 32-bit accesses are supported") - generate - if (`XLEN == 64) begin:gpio - always_comb - if (entryd[2]) begin - Din = HWDATA[63:32]; - HREADGPIO = {Dout,32'b0}; - end else begin - Din = HWDATA[31:0]; - HREADGPIO = {32'b0,Dout}; - end - end else begin:gpio // 32-bit - always_comb begin - Din = HWDATA[31:0]; - HREADGPIO = Dout; - end - end - endgenerate + if (`XLEN == 64) begin:gpio + assign Din = entryd[2] ? HWDATA[63:32] : HWDATA[31:0]; + assign HREADGPIO = entryd[2] ? {Dout,32'b0} : {32'b0,Dout}; + end else begin:gpio // 32-bit + assign Din = HWDATA[31:0]; + assign HREADGPIO = Dout; + end // register access always_ff @(posedge HCLK, negedge HRESETn) begin