import os

root = os.path.abspath(os.path.dirname(__file__))
attr_file = os.path.join(root, 'attributes.yaml')

license_header = '''
/*
See LICENSE for details
This file has been generated by CSR-BOX - {0}
Time of Generation: {1}
*/
'''

csr_str_temp = '''
                  `{0}: return "c{1}_{2}";'''

user_trap_csrs = [0x000, 0x004, 0x005, 0x040, 0x041, 0x042, 0x043, 0x044]

standard_csr_fields = [
    'description', 'address', 'priv_mode', 'reset-val', 'implemented', 'msb',
    'lsb', 'type', 'shadow', 'accessible', 'fields'
]

time_csr = ['mtime', 'mtimeh', 'time', 'timeh']

temp_register = '''
    /*doc:reg: {0}*/
    Reg#(Bit#({1})) rg_{2} <- mkReg({3});
'''

temp_shadow_reg = '''
    /*doc:reg: {0}*/
    Reg#(Bit#({1})) rg_{2} = {3};
'''

temp_wire = '''
    /*doc:wire: */
    Wire#(Bit#({0})) rg_{1} <- mkWire();
'''

temp_readOnlyRegister = '''
    /*doc:reg: {0}*/
    Reg#(Bit#({1})) rg_{2} = readOnlyReg({3});
'''

temp_wlrlReg = '''
    function Reg#(Bit#({1})) wlrlReg_{2}(Reg#(Bit#({4})) r);
        return (interface Reg;
            method Bit#({1}) _read = zeroExtend(r);
            method Action _write(Bit#({1}) x);
                r._write(truncate(x));
            endmethod
        endinterface);
    endfunction: wlrlReg_{2}

    /*doc:reg: {0}*/
    Reg#(Bit#({4})) rg_{2}_wlrl <- mkReg({3});
    Reg#(Bit#({1})) rg_{2} = wlrlReg_{2}(rg_{2}_wlrl);
'''

temp_warlReg = '''
    function Reg#(Bit#({1})) warlReg_{2}(Reg#(Bit#({1})) r);
        return (interface Reg;
            method Bit#({1}) _read = r;
            method Action _write(Bit#({1}) x);
                {4}
            endmethod
        endinterface);
    endfunction: warlReg_{2}

    /*doc:reg: {0}*/
    Reg#(Bit#({1})) rg_{2}_warl <- mkReg({3});
    Reg#(Bit#({1})) rg_{2} = warlReg_{2}(rg_{2}_warl);
'''

temp_method_shadow = '''
    method Action ma_read_{1} (Bit#({0}) _{1});
        rg_{1} <= _{1};
    endmethod
'''

temp_req_connection = '''
    mkConnection({0}.mav_fwd_req,{1}.ma_core_req);'''

temp_prv_connection = '''
    mkConnection({0}.ma_upd_privilege, rg_prv);'''

temp_top_csr_connection = '''
    mkConnection({0}.ma_read_{1}, {2}.mv_csr_{1});'''

concat_temp = '''
    /*doc:reg: {0} */
    Reg#(Bit#({1})) rg_{2} = concatReg{3}({4});
'''

readonly_temp = ''' readOnlyReg({0}'d0) '''

address_temp = '''
`define {0} 12'h{1}'''

case_address_temp = '''
                  `{0}: {1} valid= True;'''

package_temp = '''
package {0};
   
import Vector :: *;
import FIFOF :: * ;
import DReg :: * ;
import UniqueWrappers :: * ;
import ConcatReg :: * ;
import GetPut :: * ;
import Connectable :: * ;
import csr_types :: * ;
`include "csrbox.defines"
'''

interface_temp = '''
  // Interaface declaration
  interface Ifc_{0};
'''

methodv_dec_temp = '''
    method Bit#({0}) mv_csr_{1};'''
methoda_read_temp = '''
    method Action ma_read_{1} ({0});'''
method_station_generic = '''    
    /*doc:method : to receive the request from the core or previous node" */
    method Action ma_core_req(CSRReq req); 

    /*doc:method : to send response to core on a hit in this node" */
    method CSRResponse mv_core_resp;

    /*doc:method: fetch from core the prvilege mode */
    method Action ma_upd_privilege (Privilege_mode prv);
    '''

method_fwd_temp = '''
    /*doc:method: to forward the request to the next node on a miss in current node*/
    method ActionValue#(CSRReq) mav_fwd_req;
'''

method_top_def_temp = '''
    method ma_core_req = grp1.ma_core_req;
    method mv_core_resp = CSRResponse{hit:anyhit, data: anydata};
    method mv_prv = rg_prv;'''


method_top_ret_temp = '''
    method ActionValue#(Bit#({0})) mav_upd_on_ret (Privilege_mode prv);
      Bit#(TSub#({0},1)) lv_epc = ?;
'''
method_top_ret_machine_temp = '''
      if (prv == Machine) begin
        {0}.ma_set_mstatus_mpie(1'b1);
        {0}.ma_set_mstatus_mie({0}.mv_csr_mstatus[7]);
        rg_prv <= unpack({0}.mv_csr_mstatus[12:11]);
        lv_epc = truncateLSB({1}.mv_csr_mepc);
        if (lv_misa_u == 1)
          {0}.ma_set_mstatus_mpp(pack(User));
        else
          {0}.ma_set_mstatus_mpp(pack(Machine));
        if (grp1.mv_csr_mstatus[12:11] != '1)
          {0}.ma_set_mstatus_mprv(0);
      end
      if (lv_misa_c == 0)
        lv_epc[0] = 0;
      return {{lv_epc, 1'b0}};
    endmethod
'''
method_top_ret_user_temp = '''
      if (prv == User) begin
        {0}.ma_set_mstatus_upie(1'b1);
        {0}.ma_set_mstatus_uie({0}.mv_csr_mstatus[4]);
        lv_epc = truncateLSB({1}.mv_csr_uepc);
        rg_prv <= User;
        {0}.ma_set_mstatus_mprv(0);
      end
'''
method_top_ret_supervisor_temp = '''
      if (prv == Supervisor) begin
        {0}.ma_set_mstatus_spie(1'b1);
        {0}.ma_set_mstatus_sie({0}.mv_csr_mstatus[5]);
        rg_prv <= unpack(zeroExtend({0}.mv_csr_mstatus[8]));
        lv_epc = truncateLSB({1}.mv_csr_sepc);
        if (lv_misa_u == 1)
          {0}.ma_set_mstatus_spp(0);
        else
          {0}.ma_set_mstatus_spp(1);
        {0}.ma_set_mstatus_mprv(0);
      end
'''
method_top_trap_temp = '''    
    method ActionValue#(Bit#({0})) mav_upd_on_trap(Bit#(6) cause, Bit#({0}) pc, Bit#({0}) tval);
      Bit#(5) lv_cause = truncate(cause);
      Bit#(1) lv_trap_type = truncateLSB(cause);
      Bit#({0}) lv_tvec = ?;
      Privilege_mode prv = Machine;
      Bool delegateM = False;
      Bool delegateS = False;
'''

method_top_trap_medeleg = '''
      let medeleg = {0}.mv_csr_medeleg;
      let mideleg = {1}.mv_csr_mideleg;
      delegateM = (truncate(mideleg >> lv_cause) & lv_trap_type) == 1 ||
                       (truncate(medeleg >> lv_cause) & ~lv_trap_type) == 1;

      if (delegateM && (pack(rg_prv) <= pack(Supervisor)) && (lv_misa_s == 1))
        prv = Supervisor;
      else if (delegateM && delegateS && rg_prv == User && lv_misa_n == 1 && lv_misa_s == 1)
        prv = User;
      else if (delegateM && rg_prv == User && lv_misa_n == 1 && lv_misa_s == 0)
        prv = User;
'''

method_top_trap_sedeleg = '''
      let sedeleg = {0}.mv_csr_sedeleg;
      let sideleg = {1}.mv_csr_sideleg;
      delegateS = (truncate(sideleg >> lv_cause) & lv_trap_type) == 1 ||
                       (truncate(sedeleg >> lv_cause) & ~lv_trap_type) == 1;
'''

method_top_trap_debug_temp = '''
      if ( (lv_trap_type == 0 && (lv_cause == `halt_ebreak || 
                                lv_cause == `halt_trigger ||
                                lv_cause == `halt_step ||
                                lv_cause == `halt_reset ))
            || (lv_trap_type == 1 && lv_cause == `halt_interrupt)) begin
        {0}.ma_set_dpc(pc);
        {1}.ma_set_dcsr_cause(truncate(lv_cause));
        rg_core_halted <= 1;
        {1}.ma_set_dcsr_prv(pack(rg_prv));
        rg_prv <= Machine;
        lv_tvec = {2}.mv_csr_dtvec;
      end
      else if (lv_trap_type == 1 && lv_cause == `resume_interrupt) begin
        lv_tvec = {{truncateLSB({0}.mv_csr_dpc),1'b0}};
        rg_core_halted <= 0;
        rg_prv <= unpack({1}.mv_csr_dcsr[1:0]);
      end
      else
'''

method_top_debug_dec = '''
    method Bit#(1) mv_core_halted;
    method Bit#(1) mv_core_hasreset;
'''
method_top_debug_def = '''
    method mv_core_halted = rg_core_halted;
    method mv_core_hasreset = rg_core_has_reset;
'''

method_top_trap_machine_temp = '''
      if (prv == Machine) begin
        rg_prv <= Machine;
        {0}.ma_set_mtval(tval);
        {1}.ma_set_mepc(pc);
        {2}.ma_set_mcause({{lv_trap_type, 'd0, lv_cause}});
        {3}.ma_set_mstatus_mie(1'b0);
        {3}.ma_set_mstatus_mpp(pack(rg_prv));
        {3}.ma_set_mstatus_mpie({3}.mv_csr_mstatus[3]);
        Bit#(2) lv_trapmode = truncate({4}.mv_csr_mtvec);
        lv_tvec = {{truncateLSB({4}.mv_csr_mtvec),2'b0}};
        if ( lv_trapmode == 1 && lv_trap_type == 1)
            lv_tvec =  lv_tvec + {{zeroExtend(lv_cause),2'b0}};
      end
      return lv_tvec;
    endmethod
'''
method_top_trap_supervisor_temp = '''
      if (prv == Supervisor) begin
        rg_prv <= Supervisor;
        {0}.ma_set_stval(tval);
        {1}.ma_set_sepc(pc);
        {2}.ma_set_scause({{lv_trap_type, 'd0, lv_cause}});
        {3}.ma_set_mstatus_sie(1'b0);
        {3}.ma_set_mstatus_spp(truncate(pack(rg_prv)));
        {3}.ma_set_mstatus_spie({3}.mv_csr_mstatus[1]);
        Bit#(2) lv_trapmode = truncate({4}.mv_csr_stvec);
        lv_tvec = {{truncateLSB({4}.mv_csr_stvec),2'b0}};
        if ( lv_trapmode == 1 && lv_trap_type == 1)
          lv_tvec =  lv_tvec + {{zeroExtend(lv_cause),2'b0}};
      end
      else
'''
method_top_trap_user_temp = '''
      if (prv == User) begin
        rg_prv <= User;
        {0}.ma_set_utval(tval);
        {1}.ma_set_uepc(pc);
        {2}.ma_set_ucause({{lv_trap_type, 'd0, lv_cause}});
        {3}.ma_set_mstatus_uie(1'b0);
        {3}.ma_set_mstatus_upie({3}.mv_csr_mstatus[0]);
        Bit#(2) lv_trapmode = truncate({4}.mv_csr_utvec);
        lv_tvec = {{truncateLSB({4}.mv_csr_stvec),2'b0}};
        if ( lv_trapmode == 1 && lv_trap_type == 1)
          lv_tvec =  lv_tvec + {{zeroExtend(lv_cause),2'b0}};
      end
      else
'''

end_interface_temp = '''
  endinterface
'''
module_temp = '''
  //Module Declarations
  (*synthesize*)
  
  (*conflict_free="ma_core_req,mv_core_resp"*)
{1}
  module mk_{0}{2}(Ifc_{0});
'''

methodv_def_temp = '''
    method mv_csr_{0} = {1}{2};
'''

methoda_top_temp = '''
    method {0} = {1}.{0};'''

end_module_temp = '''
  endmodule '''

endcase_temp = '''
            default: begin
                rg_resp_to_core <= CSRResponse{hit: True, data: 0};
            end
        endcase
        endmethod
    '''
endcase_fwd_temp = '''
            default: begin
                ff_fwd_request.enq(req);
                rg_resp_to_core <= CSRResponse{hit: False, data: 0};
            end
        endcase
        endmethod
    '''

end_package_temp = '''
endpackage 
'''

func_temp = '''
    function Bit#({0}) fn_csr_op (Bit#({0}) writedata, Bit#({0}) readdata, Bit#(2) op);
        if(op == 'd1)
    	    return writedata;
        else if(op == 'd2)
            return (writedata|readdata);
        else
            return (~writedata & readdata);
    endfunction
  '''

func_decoder = '''
    function Bool address_valid(Bit#(12) addr, Bit#(26) misa);
    Bool valid=False;
    case(addr)
   '''

func_csr_to_csr = '''
    function String fn_csr_to_str(Bit#(12) addr);
    case(addr)
    '''

method_csr_req_def_temp = ''' 
        method Action ma_core_req(CSRReq req);
        Bit#(2) op = req.funct3; '''

method_case_req = '''
        case (req.csr_address) '''

method_generic_def_temp = '''
    method mv_core_resp = rg_resp_to_core;

    method Action ma_upd_privilege (Privilege_mode prv);
        wr_prv <= prv;
    endmethod'''

method_fwd_def_temp = '''
        method ActionValue#(CSRReq) mav_fwd_req;
            ff_fwd_request.deq;
            return ff_fwd_request.first();
        endmethod
'''
case_def = '''
            `{0} : begin
                Bit#({2}) readdata = zeroExtend(rg_{1});
                rg_resp_to_core <= CSRResponse{{hit:True, data: readdata}};
                let word = fn_csr_op(req.writedata, readdata, op);
                
                {3} rg_{1} <= truncate(word);
            end
'''
case_def_ro = '''
            `{0} : begin
                Bit#({2}) readdata = zeroExtend(rg_{1});
                rg_resp_to_core <= CSRResponse{{hit:True, data: readdata}};
            end
'''
csrreq_struct_temp = '''
    typedef struct {{
        Bit#(12) csr_address;
        Bit#({0}) writedata;
        Bit#(2) funct3;
        {1}
    }} CSRReq deriving(Bits, FShow, Eq);

    typedef struct{{
        Bool hit;
        Bit#({0})  data;
    }} CSRResponse deriving(Bits, Eq, FShow);

    typedef enum {{Machine = 3, Supervisor = 1, User = 0}} Privilege_mode deriving(Bits, Eq, FShow);

'''

other_vars_temp = '''

    /*doc:wire: holds the response of this group for a csr operation request,
    for one cycle, wire is used for low latency*/
    Wire#(CSRResponse) rg_resp_to_core <- mkDWire(CSRResponse{hit:False, data:0});

    /*doc:fifo: fifo to forward the core request to the next group on a miss*/
    FIFOF#(CSRReq) ff_fwd_request <- mkFIFOF1();

    /*doc:wire: holds the current privilege mode of the hart*/
    Wire#(Privilege_mode) wr_prv <- mkWire();
'''

check_hit_temp = '''
    Bool anyhit = {0};
    Bit#({2}) anydata = {1};
'''

method_top_generic = '''    
    /*doc:method : to receive the request from the core or previous node" */
    method Action ma_core_req(CSRReq req); 

    /*doc:method : to send response to core on a hit in this node" */
    method CSRResponse mv_core_resp;

    method ActionValue#(Bit#({0})) mav_upd_on_ret (Privilege_mode prv);
    
    method ActionValue#(Bit#({0})) mav_upd_on_trap(Bit#(6) cause, Bit#({0}) pc, Bit#({0}) tval);

    method Privilege_mode mv_prv;

'''

pmp_ifc = '''
    method Vector#({0}, Bit#(8)) mv_pmpcfg;
    method Vector#({0}, Bit#({1})) mv_pmpaddr;'''

pmpaddr_def = '''
    method Vector#({0}, Bit#({1})) mv_pmpaddr;
        Vector#({0}, Bit#({1})) lv_pmpaddr;
{2}
        return lv_pmpaddr;
    endmethod:mv_pmpaddr
'''
pmpcfg_def = '''
    method Vector#({0}, Bit#(8)) mv_pmpcfg;
        Vector#({0}, Bit#(8)) lv_pmpcfg;
{1}
        return lv_pmpcfg;
    endmethod:mv_pmpcfg
'''
same_groups_rv32 = [
        ('SSTATUS', 'MSTATUS'),
        ('USTATUS', 'MSTATUS'),
        ('MSTATUS', 'FCSR'),
        ('FRM', 'FCSR'),
        ('FFLAGS', 'FCSR'),
        ('MHPMCOUNTER3', 'MHPMCOUNTER3H'),
        ('MHPMCOUNTER4', 'MHPMCOUNTER4H'),
        ('MHPMCOUNTER5', 'MHPMCOUNTER5H'),
        ('MHPMCOUNTER6', 'MHPMCOUNTER6H'),
        ('MHPMCOUNTER7', 'MHPMCOUNTER7H'),
        ('MHPMCOUNTER8', 'MHPMCOUNTER8H'),
        ('MHPMCOUNTER9', 'MHPMCOUNTER9H'),
        ('MHPMCOUNTER10', 'MHPMCOUNTER10H'),
        ('MHPMCOUNTER11', 'MHPMCOUNTER11H'),
        ('MHPMCOUNTER12', 'MHPMCOUNTER12H'),
        ('MHPMCOUNTER13', 'MHPMCOUNTER13H'),
        ('MHPMCOUNTER14', 'MHPMCOUNTER14H'),
        ('MHPMCOUNTER15', 'MHPMCOUNTER15H'),
        ('MHPMCOUNTER16', 'MHPMCOUNTER16H'),
        ('MHPMCOUNTER17', 'MHPMCOUNTER17H'),
        ('MHPMCOUNTER18', 'MHPMCOUNTER18H'),
        ('MHPMCOUNTER19', 'MHPMCOUNTER19H'),
        ('MHPMCOUNTER20', 'MHPMCOUNTER20H'),
        ('MHPMCOUNTER21', 'MHPMCOUNTER21H'),
        ('MHPMCOUNTER22', 'MHPMCOUNTER22H'),
        ('MHPMCOUNTER23', 'MHPMCOUNTER23H'),
        ('MHPMCOUNTER24', 'MHPMCOUNTER24H'),
        ('MHPMCOUNTER25', 'MHPMCOUNTER25H'),
        ('MHPMCOUNTER26', 'MHPMCOUNTER26H'),
        ('MHPMCOUNTER27', 'MHPMCOUNTER27H'),
        ('MHPMCOUNTER28', 'MHPMCOUNTER28H'),
        ('MHPMCOUNTER29', 'MHPMCOUNTER29H'),
        ('MHPMCOUNTER30', 'MHPMCOUNTER30H'),
        ('MHPMCOUNTER31', 'MHPMCOUNTER31H'),
        ('HPMCOUNTER3', 'HPMCOUNTER3H'),
        ('HPMCOUNTER4', 'HPMCOUNTER4H'),
        ('HPMCOUNTER5', 'HPMCOUNTER5H'),
        ('HPMCOUNTER6', 'HPMCOUNTER6H'),
        ('HPMCOUNTER7', 'HPMCOUNTER7H'),
        ('HPMCOUNTER8', 'HPMCOUNTER8H'),
        ('HPMCOUNTER9', 'HPMCOUNTER9H'),
        ('HPMCOUNTER10', 'HPMCOUNTER10H'),
        ('HPMCOUNTER11', 'HPMCOUNTER11H'),
        ('HPMCOUNTER12', 'HPMCOUNTER12H'),
        ('HPMCOUNTER13', 'HPMCOUNTER13H'),
        ('HPMCOUNTER14', 'HPMCOUNTER14H'),
        ('HPMCOUNTER15', 'HPMCOUNTER15H'),
        ('HPMCOUNTER16', 'HPMCOUNTER16H'),
        ('HPMCOUNTER17', 'HPMCOUNTER17H'),
        ('HPMCOUNTER18', 'HPMCOUNTER18H'),
        ('HPMCOUNTER19', 'HPMCOUNTER19H'),
        ('HPMCOUNTER20', 'HPMCOUNTER20H'),
        ('HPMCOUNTER21', 'HPMCOUNTER21H'),
        ('HPMCOUNTER22', 'HPMCOUNTER22H'),
        ('HPMCOUNTER23', 'HPMCOUNTER23H'),
        ('HPMCOUNTER24', 'HPMCOUNTER24H'),
        ('HPMCOUNTER25', 'HPMCOUNTER25H'),
        ('HPMCOUNTER26', 'HPMCOUNTER26H'),
        ('HPMCOUNTER27', 'HPMCOUNTER27H'),
        ('HPMCOUNTER28', 'HPMCOUNTER28H'),
        ('HPMCOUNTER29', 'HPMCOUNTER29H'),
        ('HPMCOUNTER30', 'HPMCOUNTER30H'),
        ('HPMCOUNTER31', 'HPMCOUNTER31H'),
        ('CYCLE', 'CYCLEH'),
        ('MINSTRET', 'MINSTRETH'),
        ('TIME', 'TIMEH'),
        ('MIE', 'SIE'),
        ('MIE', 'UIE'),
        ('MIP', 'SIP'),
        ('MIP', 'UIP')
        ]

same_groups_rv64 = [
        ('SSTATUS', 'MSTATUS'),
        ('USTATUS', 'MSTATUS'),
        ('MSTATUS', 'FCSR'),
        ('FRM', 'FCSR'),
        ('FFLAGS', 'FCSR'),
        ('MIE', 'SIE'),
        ('MIE', 'UIE'),
        ('MIP', 'SIP'),
        ('MIP', 'UIP'),
        ]

necessary_pairs_rv32 = [
        ('MHPMCOUNTER3', 'MHPMCOUNTER3H'),
        ('MHPMCOUNTER4', 'MHPMCOUNTER4H'),
        ('MHPMCOUNTER5', 'MHPMCOUNTER5H'),
        ('MHPMCOUNTER6', 'MHPMCOUNTER6H'),
        ('MHPMCOUNTER7', 'MHPMCOUNTER7H'),
        ('MHPMCOUNTER8', 'MHPMCOUNTER8H'),
        ('MHPMCOUNTER9', 'MHPMCOUNTER9H'),
        ('MHPMCOUNTER10', 'MHPMCOUNTER10H'),
        ('MHPMCOUNTER11', 'MHPMCOUNTER11H'),
        ('MHPMCOUNTER12', 'MHPMCOUNTER12H'),
        ('MHPMCOUNTER13', 'MHPMCOUNTER13H'),
        ('MHPMCOUNTER14', 'MHPMCOUNTER14H'),
        ('MHPMCOUNTER15', 'MHPMCOUNTER15H'),
        ('MHPMCOUNTER16', 'MHPMCOUNTER16H'),
        ('MHPMCOUNTER17', 'MHPMCOUNTER17H'),
        ('MHPMCOUNTER18', 'MHPMCOUNTER18H'),
        ('MHPMCOUNTER19', 'MHPMCOUNTER19H'),
        ('MHPMCOUNTER20', 'MHPMCOUNTER20H'),
        ('MHPMCOUNTER21', 'MHPMCOUNTER21H'),
        ('MHPMCOUNTER22', 'MHPMCOUNTER22H'),
        ('MHPMCOUNTER23', 'MHPMCOUNTER23H'),
        ('MHPMCOUNTER24', 'MHPMCOUNTER24H'),
        ('MHPMCOUNTER25', 'MHPMCOUNTER25H'),
        ('MHPMCOUNTER26', 'MHPMCOUNTER26H'),
        ('MHPMCOUNTER27', 'MHPMCOUNTER27H'),
        ('MHPMCOUNTER28', 'MHPMCOUNTER28H'),
        ('MHPMCOUNTER29', 'MHPMCOUNTER29H'),
        ('MHPMCOUNTER30', 'MHPMCOUNTER30H'),
        ('MHPMCOUNTER31', 'MHPMCOUNTER31H'),
        ('HPMCOUNTER3', 'HPMCOUNTER3H'),
        ('HPMCOUNTER4', 'HPMCOUNTER4H'),
        ('HPMCOUNTER5', 'HPMCOUNTER5H'),
        ('HPMCOUNTER6', 'HPMCOUNTER6H'),
        ('HPMCOUNTER7', 'HPMCOUNTER7H'),
        ('HPMCOUNTER8', 'HPMCOUNTER8H'),
        ('HPMCOUNTER9', 'HPMCOUNTER9H'),
        ('HPMCOUNTER10', 'HPMCOUNTER10H'),
        ('HPMCOUNTER11', 'HPMCOUNTER11H'),
        ('HPMCOUNTER12', 'HPMCOUNTER12H'),
        ('HPMCOUNTER13', 'HPMCOUNTER13H'),
        ('HPMCOUNTER14', 'HPMCOUNTER14H'),
        ('HPMCOUNTER15', 'HPMCOUNTER15H'),
        ('HPMCOUNTER16', 'HPMCOUNTER16H'),
        ('HPMCOUNTER17', 'HPMCOUNTER17H'),
        ('HPMCOUNTER18', 'HPMCOUNTER18H'),
        ('HPMCOUNTER19', 'HPMCOUNTER19H'),
        ('HPMCOUNTER20', 'HPMCOUNTER20H'),
        ('HPMCOUNTER21', 'HPMCOUNTER21H'),
        ('HPMCOUNTER22', 'HPMCOUNTER22H'),
        ('HPMCOUNTER23', 'HPMCOUNTER23H'),
        ('HPMCOUNTER24', 'HPMCOUNTER24H'),
        ('HPMCOUNTER25', 'HPMCOUNTER25H'),
        ('HPMCOUNTER26', 'HPMCOUNTER26H'),
        ('HPMCOUNTER27', 'HPMCOUNTER27H'),
        ('HPMCOUNTER28', 'HPMCOUNTER28H'),
        ('HPMCOUNTER29', 'HPMCOUNTER29H'),
        ('HPMCOUNTER30', 'HPMCOUNTER30H'),
        ('HPMCOUNTER31', 'HPMCOUNTER31H'),
        ('CYCLE', 'CYCLEH'),
        ('MINSTRET', 'MINSTRETH'),
        ('TIME', 'TIMEH')
        ]
