#! /usr/bin/env python3
import xlrd
import sys

workbook = xlrd.open_workbook(sys.argv[1], formatting_info=True)
sheet = workbook.sheets()[0]
regblock = sys.argv[1].split('.')[0]

cur_row = 0
register = {}
table = []
idx_top = -1
for value in sheet.col_values(0)[1:]:
    cur_row += 1
    if value != "":
        if register : 
            table.append(register)
        register = {}
        idx_top = -1
        register["name"] = sheet.cell_value(cur_row,1)
        register["addr"] = value.replace("0x","'h")
        register["type"] = sheet.cell_value(cur_row,2).lower()
        if register["type"] == "" :
            register["type"] = "rw"
        register["field"] = []
    field = {}
    field["name"] = sheet.cell_value(cur_row,3).split('[')[0]
    if sheet.cell_value(cur_row,2) != "" :
        field["type"] = sheet.cell_value(cur_row,2).lower()
    else :
        field["type"] = register["type"]
    start_end_value = sheet.cell_value(cur_row,4).replace('[','').replace(']','').replace(',',':').split(':')
    if start_end_value[-1] == start_end_value[0]:
        start_end_value.append(start_end_value[0])
    field["start_bit"] = start_end_value[1]
    field["end_bit"] = start_end_value[0]

    if idx_top != -1 and idx_top != 1+int(field["end_bit"]) :
        ######## insert reserved bit field
        field2 = {}
        field2["name"] = f"rsvd_{1+int(field['end_bit'])}"
        field2["type"] = "ro"
        field2["start_bit"] = 1+int(field["end_bit"])
        field2["end_bit"] = idx_top-1
        field2["default_value"] = "'h0"
        register["field"].append(field2)

    idx_top = int(field["start_bit"])
    field["default_value"] = sheet.cell_value(cur_row,5).replace("0x","'h").replace("0X","'h")
    if field["default_value"] == "" :
        field["default_value"] = 0
    register["field"].append(field)
else :
    if register : 
        table.append(register)
#for register in table :
#    print( f"register {register['name']} {{")
#    print(  "   bytes 4;")
#    for field in register['field'] :
#        print( f"   field {field['name']} @'d{field['start_bit']} {{")
#        print( f"       bits {int(field['end_bit']) - int(field['start_bit']) + 1};")
#        print( f"       access {register['type']};")
#        print( f"       reset {field['default_value']};")
#        print(  "       constraint empty {}")
#        print(  "   }")
#    print(  "}")
#    print(  "")
rd = open(f"{regblock}.ralf","w")
rd.write( f'block {regblock} {{\n')
rd.write(  "    bytes 4;\n")
for register in table :
    rd.write( f"    register {register['name']} @{register['addr']} {{\n")
    rd.write(  "        bytes 4;\n")
    for field in register['field'] :
        print(f"start build {register['name']} -> field {field['name']}.")
        rd.write( f"        field {field['name']} @'d{field['start_bit']} {{\n")
        rd.write( f"            bits {int(field['end_bit']) - int(field['start_bit']) + 1};\n")
        rd.write( f"            access {field['type']};\n")
        rd.write( f"            reset {field['default_value']};\n")
        rd.write(  "            constraint empty {}\n")
        rd.write(  "        }\n")
    rd.write(  "    }\n")
    rd.write(  "\n")
rd.write(  '}\n')
rd.close();

reg_idx = -1
rd = open(f"{regblock}.h","w")
rd.write(f"#ifndef {regblock}__H\n")
rd.write(f"#define {regblock}__H\n")
rd.write('#include "stdint.h"\n')
rd.write("typedef volatile struct {\n")
for register in table :

    sub_idx = 0x61    ######### 'a'
    reg_tmp = int(register["addr"].replace("'h",""),16)
    if reg_idx != -1 and reg_idx != reg_tmp :
        ######## insert reserved registers definition (filler bytes)
        rd.write (f"    uint32_t rsvd_{hex(reg_idx)}[{hex(reg_tmp-reg_idx)}/4];\n\n")
    reg_idx = reg_tmp + 4

    rd.write ("    union {\n")
    rd.write ("        struct {\n")
    for field in reversed(register['field']):
        if int(field['end_bit']) < int(field['start_bit']) :
            ######## restart bit field definition
            rd.write (f"        }} {register['name']}_{chr(sub_idx)};\n")
            sub_idx = sub_idx + 1
            rd.write ("        struct {\n")
        else :
            rd.write (f"            uint32_t {field['name']}:{int(field['end_bit']) - int(field['start_bit']) + 1};\n")
    rd.write (f"        }} {register['name']};\n")
    rd.write (f"        uint32_t {register['name']}_W;\n")
    rd.write ("    };\n")
    rd.write("\n")
rd.write(f"}} {regblock}_s;\n")
rd.write("#endif\n")
rd.close()


#print(sheet.name) 
#print(sheet.nrows, sheet.ncols) 
#print(sheet.row(rowx=0)) 
#print(sheet.row_len(rowx=0)) 
#print(sheet.col(colx=0)) 
#print(sheet.cell(rowx=1, colx=0)) 
#print(sheet.cell(rowx=2, colx=0)) 
#print(sheet.row_values(1))
#print(sheet.row_values(1, start_colx=0, end_colx=None))
#print(sheet.col_values(0)) 
#print(sheet.col_values(0, start_rowx=1, end_rowx=2))
#print(sheet.cell_value(rowx=0, colx=0))
#list_a = []
#for i in range(0, sheet.nrows, 1):
#    tmp = []
#    for j in range(0, sheet.ncols, 1):
#        cell_type = sheet.cell_type(i, j)
#        cell_value = sheet.cell_value(i, j)
#
#        if cell_type == 3:            
#            tmp.append(xlrd.xldate_as_datetime(
#                cell_value, workbook.datemode).strftime('%Y-%m-%d %H:%M:%S'))
#        else:
#            tmp.append(cell_value)
#    list_a.append(tmp)
#print(list_a)
#
#print(sheet.merged_cells)
#for (row_start, row_end, col_start, col_end) in sheet.merged_cells:
#    print(sheet.cell_value(rowx=row_start, colx=col_start)) 
