; --------------------------------------------------------------------------------
; @Title: Windriver register definition (.reg) to PRACTICE converter
; @Description:
;   This script parses a windriver register definition files and converts
;   all lines starting with "SCGA" to PER.Set commands. All other lines
;   are ignored.
; @Keywords: converter, script, windriver
; @Author: HDA, REI
; @Copyright: (C) 1989-2016 Lauterbach GmbH, licensed for use with TRACE32(R) only
; --------------------------------------------------------------------------------
; $Id: scga2practice.cmm 15994 2020-04-28 16:00:56Z rweiss $

; configure parameters
LOCAL &cf_tar &cpufamily &first_scga
&cf_tar=""
&cpufamily=""
&first_scga=TRUE()

LOCAL &sysobasetrigger &sysobaseaddr
&sysobasetrigger=-1
&sysobaseaddr=""

; default anchors (base addresses of register blocks)
LOCAL &anchor_0 &anchor_1 &anchor_2 &anchor_3 &anchor_4 &anchor_5 &anchor_6 &anchor_7 &anchor_8
&anchor_0=0x00000000
&anchor_1=0x00000000
&anchor_2=0x00000000
&anchor_3=0x00000000
&anchor_4=0x00000000
&anchor_5=0x00000000
&anchor_6=0x00000000
&anchor_7=0x00000000
&anchor_8=0x00000000

; JTAG debug unit-internal temporary register
LOCAL &temp_0 &temp_1 &temp_2 &temp_3 &temp_4 &temp_5 &temp_6 &temp_7 &temp_8

; Disabled group storage
LOCAL &cf_grp_disabled_list
&cf_grp_disabled_list=","

; ask for file to convert
LOCAL &input_file
LOCAL &ouput_file
DIALOG.File "*.reg"
ENTRY %LINE &input_file
IF "&input_file"==""
  ENDDO
&ouput_file="&input_file.cmm"

; open / create files
OPEN #1 "&input_file" /Read
OPEN #2 "&ouput_file" /Create /Write

; write header into output file
WRITE #2 "; Generated "+CLOCK.DATE()+", "+CLOCK.TIME()
WRITE #2 "; source file: &input_file"
WRITE #2 ""

LOCAL &linecount &errorcount
&linecount=0
&errorcount=0

; parse input file, first pass (collect disabled group information)
RePeaT
(
  LOCAL &command &readLine &result
  READ #1 &command %LINE &readLine
  &linecount=&linecount+1
  &command=CONVert.TOUPPER("&command")
  &readLine=CONVert.TOUPPER(STRing.TRIM("&readLine"))
  &result=""

  ON ERROR GOSUB
  (
    LOCAL &lstr
    &lstr=FORMAT.Decimal(1.,&linecount)
    WRITE #2 "STOP ""SYNTAX ERROR IN LINE &lstr"""
    CLOSE #1
    CLOSE #2
    PRINT %ERROR "Syntax error found in line &lstr"
    DIALOG.OK "Syntax error found in line &lstr"
    ENDDO
  )

  IF "&command"=="SC"
  (
    ;reset groups if "SC GRP ERASE" found
    IF STRing.MID("&readLine",0,3)=="GRP"
    (
      &readLine=STRing.TRIM(STRing.MID("&readline",3,STRing.LENgth("&readline")))
      IF STRing.MID("&readLine",0,5)=="ERASE"
      (
        &cf_grp_disabled_list=","
      )
    )
  )
  ELSE IF "&command"=="CF"
  (
    GOSUB Decode_CF_1 &readLine
    ENTRY %LINE &result
  )
)
WHILE !FILE.EOF(1)
CLOSE #1
; parse input file, second pass
OPEN #1 "&input_file" /Read
&linecount=0
RePeaT
(
  LOCAL &command &readLine &result
  READ #1 &command %LINE &readLine
  &linecount=&linecount+1
  &command=CONVert.TOUPPER("&command")
  &readLine=CONVert.TOUPPER(STRing.TRIM("&readLine"))
  &result=""

  ON ERROR GOSUB
  (
    LOCAL &lstr
    &lstr=FORMAT.Decimal(1.,&linecount)
    WRITE #2 "STOP ""SYNTAX ERROR IN LINE &lstr"""
    CLOSE #1
    CLOSE #2
    PRINT %ERROR "Syntax error found in line &lstr"
    DIALOG.OK "Syntax error found in line &lstr"
    ENDDO
  )

  IF "&command"=="SCGA"
  (
    IF &first_scga
    (
      &first_scga=FALSE()
      WRITE #2 "SYStem.Up"
    )

    GOSUB Decode_SCGA &readLine
    ENTRY %LINE &result
  )
  ELSE IF "&command"=="CF"
  (
    GOSUB Decode_CF_2 &readLine
    ENTRY %LINE &result
    IF "&result"==""
    (
      ; insert as comment
      &result="; &command &readLine"
    )
  )
  ELSE IF "&command"=="TF"
  (
    GOSUB Decode_TF &readLine
    ENTRY %LINE &result
    IF "&result"==""
    (
      ; insert as comment
      &result="; &command &readLine"
    )
    ELSE IF STRing.SCAN("&result","FLASH.CFI ", 0)==0
    (
      WRITE #2 ";"
      WRITE #2 ";FLASH.CFI information:"
      WRITE #2 ";  FLASH.CFI will fail to detect the connected FLASH, if the FLASH device"
      WRITE #2 ";  does not implement the Common Flash Interface."
      WRITE #2 ";  In this case please try to set up FLASH programming manually using"
      WRITE #2 ";  FLASH.Create / FLASH.TARGET commands."
      WRITE #2 ";  Lauterbach support (support@lauterbach.com) will help you with the setup."
      WRITE #2 ";"
    )
  )
  ELSE IF "&command"!=""
  (
    ; insert as comment
    &result="; &command &readLine"
  )
  IF "&result"!=""
    WRITE #2 "&result"

  IF "&sysobaseaddr"!=""
  (
    WRITE #2 "SYStem.Option.BASE 0x"+FORMAT.HEX(8.,&sysobaseaddr)
    &sysobaseaddr=""
  )
)
WHILE !FILE.EOF(1)

CLOSE #1

WRITE #2 "ENDDO"
CLOSE #2

IF &errorcount!=0
  DIALOG.OK "Script conversion completed with errors."
ELSE
  PRINT "Script converted successfully"

PEDIT "&ouput_file"
ENDDO

; --------------------------------------------------------------------------------
; subroutines
; --------------------------------------------------------------------------------

; --------------------------------------------------------------------------------
; CF
; --------------------------------------------------------------------------------
Decode_CF_1:
  LOCAL &param &rest
  ENTRY &param %LINE &rest
  IF "&param"=="GRP"
  (
    GOSUB Decode_CF_GRP_1 &rest
  )
  RETURN

Decode_CF_GRP_1:
  LOCAL &groupname &enabled &rest
  ENTRY &groupname &enabled %LINE &rest
  IF "&enabled"=="DISABLED"
  (
    &cf_grp_disabled_list="&(cf_grp_disabled_list)&(groupname),"
  )
  RETURN


Decode_CF_2:
  LOCAL &param &value1 &rest &cmd
  ENTRY &param &value1 %LINE &rest
  IF "&param"=="TAR"
  (
    &cf_tar="&value1"
    &cmd="SYStem.CPU &value1"

    IF CPUFAMILY()=="POWERPC"
    (
      IF (STRing.MID("&cf_tar",0,1)=="8")
      (
        IF !((STRing.MID("&cf_tar",3,1)>="0")&&(STRing.MID("&cf_tar",3,1)<="9"))
          &cpufamily="MPC8XX"
        ELSE IF STRing.MID("&cf_tar",0,2)=="82"
          &cpufamily="MPC82XX"
        ELSE IF STRing.MID("&cf_tar",0,2)=="83"
          &cpufamily="MPC83XX"
        ELSE IF STRing.MID("&cf_tar",0,2)=="85"
          &cpufamily="MPC85XX"
        ELSE
          &cpufamily="MPC86XX"
      )
      IF (STRing.MID("&cf_tar",0,1)=="6")
      (
          &cpufamily="MPC6XX7XX"
      )
      IF (STRing.MID("&cf_tar",0,1)=="7")
      (
        IF !((STRing.MID("&cf_tar",3,1)>="0")&&(STRing.MID("&cf_tar",3,1)<="9"))
          &cpufamily="MPC6XX7XX"
        ELSE
          &cpufamily="MPC74XX"
      )
      IF (STRing.MID("&cf_tar",0,3)=="P10")||("&cf_tar"=="P2010")||("&cf_tar"=="P2020")
      (
        &cpufamily="MPC85XX"
      )
      ELSE IF (STRing.MID("&cf_tar",0,1)=="P")
      (
        &cpufamily="QORIQ32"
      )
    )

    ; define special function anchors
    IF ("&cpufamily"=="MPC83XX")
    (
      &anchor_0="*IOBASE.ADDRESS()+" ; anchor 0 is preset with IMMRBAR
    )
    IF ("&cpufamily"=="MPC85XX")||("&cpufamily"=="MPC86XX")||("&cpufamily"=="QORIQ32")
    (
      &anchor_0="=IOBASE.ADDRESS()+" ; anchor 0 is always CCSR base address
      &anchor_2="=IOBASE.ADDRESS()+" ; anchor 2 is always CCSR base address
    )
  )
  IF ("&param"=="RSTIMMR")&&("&value1"!="AUTO")
  (
    IF "&cpufamily"=="MPC82XX"
    (
      LOCAL &base
      &base=0x&value1
      &cmd="SYStem.Option.BASE 0x"+FORMAT.HEX(8.,&base)
      &sysobasetrigger=&base+0x000101A8
    )
  )
  RETURN &cmd

; --------------------------------------------------------------------------------
; TF
; --------------------------------------------------------------------------------
Decode_TF:
  LOCAL &param &rest
  ENTRY &param %LINE &rest
  IF "&param"=="CONF"
  (
    LOCAL &result
    GOSUB Decode_TF_CONF &rest
    ENTRY %LINE &result
    RETURN &result
  )
  RETURN

Decode_TF_CONF:
  LOCAL &devnum &ramstart &ramsize &flashstart &rest
  ENTRY &devnum &ramstart &ramsize &flashstart %LINE &rest

  &ramstart="0x&ramstart"
  &flashstart="0x&flashstart"
  &ramsize="&ramsize"+"."
  LOCAL &cmd &codeaddress &dataaddress &datasize &accessclass
  &accessclass=""
  IF ("&cpufamily"=="MPC6XX7XX")||("&cpufamily"=="MPC82XX")||("&cpufamily"=="MPC83XX")||("&cpufamily"=="MPC74XX")||("&cpufamily"=="MPC86XX")
    &accessclass="A:"
  &codeaddress=&ramstart+0x2000
  &dataaddress=&ramstart+0x3000
  &datasize=0x1000
  &cmd="FLASH.CFI "+"&(accessclass)0x"+FORMAT.HEX(8.,&flashstart)+" AUTOwidth"
  &cmd="&cmd /TARGET &(accessclass)0x"+FORMAT.HEX(8.,&codeaddress)+" &(accessclass)0x"+FORMAT.HEX(8.,&dataaddress)+" 0x"+FORMAT.HEX(8.,&datasize)
  RETURN &cmd

; --------------------------------------------------------------------------------
; SCGA
; --------------------------------------------------------------------------------
Decode_SCGA:
  LOCAL &grp &rname &addr &value &options
  ENTRY &grp &rname &addr &value %LINE &options

  ; comment out disabled groups
  LOCAL &comment
  &comment=""
  IF STRing.SCAN("&cf_grp_disabled_list",",&(grp),",0)>=0
  (
    &comment="; "
  )

  ; decode options
  LOCAL &o_no_addr &o_hide &o_lendian &o_nwf &o_r &o_ua &o_sa &o_tld &o_cpur
  &o_no_addr=(-1)!=STRing.SCAN("&options","/NO_ADDR",0)
  &o_hide=(-1)!=STRing.SCAN("&options","/HIDE",0)
  &o_lendian=(-1)!=STRing.SCAN("&options","/LENDIAN",0)
  &o_nwf=(-1)!=STRing.SCAN("&options","(NWF)",0)
  &o_r=(-1)!=STRing.SCAN("&options","/R ",0)
  &o_cpur=(-1)!=STRing.SCAN("&options","/CPUR",0)

  IF &o_cpur
  (
    ; CPU register access not supported by converter, return input line as comment
    LOCAL &wrcmd
    ENTRY %LINE &wrcmd
    &wrcmd="; &wrcmd"
    RETURN &wrcmd
  )

  ; decode special temporary register operations
  LOCAL &tldpos
  &tldpos=STRing.SCAN("&options","/TLD:",0)
  &o_tld=(-1)!=&tldpos
  IF &o_tld
  (
    LOCAL &tldval &command
    &tldval=STRing.MID("&options ",&tldpos+5,1)
    &command="&"+"temp_&tldval=0x&value"
    &command
  )

  ; decode base address options
  LOCAL &uapos &sapos &addressprefix
  &addressprefix=""
  &uapos=STRing.SCAN("&options","/UA:",0)
  &sapos=STRing.SCAN("&options","/SA:",0)
  &o_ua=(-1)!=&uapos
  &o_sa=(-1)!=&sapos
  IF &o_ua
  (
    LOCAL &uaval &macro &anchor_value
    &uaval=STRing.MID("&options ",&uapos+4,1)
    &macro="&"+"anchor_&uaval"
    &&anchor_value="&macro"
    IF (STRing.MID("&anchor_value",0,1)=="=")||(STRing.MID("&anchor_value",0,1)=="*")
    (
      &addressprefix=STRing.MID("&anchor_value",1,STRing.LENgth("&anchor_value")-1)
    )
    ELSE
    (
      &addr=0x&addr+&anchor_value
      &addr=FORMAT.HEX(8.,&addr)
    )
  )
  IF &o_sa
  (
    LOCAL &saval &macro &condition &command &old_anchor_value &new_anchor_value
    &saval=STRing.MID("&options ",&sapos+4,1)
    &macro="&"+"anchor_&saval"
    &&old_anchor_value="&macro"
    IF STRing.MID("&old_anchor_value",0,1)!="=" ; special function anchor starting with "=" not replaced
    (
      &new_anchor_value=0x&value
      &macro="&"+"temp_&saval"
      &&condition="""&macro""!="""""
      IF &condition
      (
        GOSUB Hook_Temp_&saval &new_anchor_value
        ENTRY &new_anchor_value
      )
      &command="&"+"anchor_&saval=&new_anchor_value"
      &command
    )
  )

  ; decode options added by script (for recursive calls)
  LOCAL &t32_getindregaddressreg
  &t32_getindregaddressreg=(-1)!=STRing.SCAN("&options","/t32_getindregaddressreg",0)

  IF (&o_no_addr||&o_hide||&o_r)&&(!&t32_getindregaddressreg)
    RETURN

  ; access width
  LOCAL &awidth &spacer
  IF STRing.LENgth("&value")==2.
  (
    &awidth="%Byte"
    &spacer="              "
  )
  ELSE IF STRing.LENgth("&value")==4.
  (
    &awidth="%Word"
    &spacer="            "
  )
  ELSE IF STRing.LENgth("&value")==8.
  (
    &awidth="%Long"
    &spacer="        "
  )
  ELSE IF STRing.LENgth("&value")==16.
  (
    &awidth="%Quad"
    &spacer=""
  )
  ELSE
  (
    LOCAL &message  &lstr
    &lstr=FORMAT.Decimal(1.,&linecount)
    &message="STOP ""PARSER ERROR - unsupported data width in line &lstr"""
    PRINT %ERROR "&message"
    &errorcount=&errorcount+1
    RETURN &message
  )

  ; endian
  LOCAL &endian
  IF &o_lendian
    &endian="%LE"
  ELSE
    &endian="%BE"

  IF !&o_nwf
  (
    ; simple register
    LOCAL &cmd
    &cmd="PER.Set ANC:&(addressprefix)0x&addr &awidth &endian 0x&value &spacer; &grp[&rname]"
    IF (&sysobasetrigger!=-1)&&(&sysobasetrigger==0x&addr)
    (
      &sysobaseaddr=0x&value
    )
    RETURN &comment&cmd
  )
  ELSE
  (
    IF &t32_getindregaddressreg
    (
      LOCAL &message
      &message="; PARSER ERROR - repetitive recursion not expected"
      RETURN &message
    )

    ; indirect register - get address register access
    LOCAL &nextcommand &nextline
    READ #1 &nextcommand %LINE &nextline
    &nextline=CONVert.TOUPPER(STRing.TRIM("&nextline"))
    GOSUB Decode_SCGA &nextline /t32_getindregaddressreg
    LOCAL &cmd &addreg_addr &addreg_width &addreg_endian &addreg_value &addreg_comment
    ENTRY &cmd &addreg_addr &addreg_width &addreg_endian &addreg_value %LINE &addreg_comment
    &cmd="PER.Set.SaveIndex &addreg_addr &addreg_width &addreg_endian &addreg_value &addreg_value ANC:&(addressprefix)0x&addr &awidth &endian 0x&value &spacer; &grp[&rname]"
    RETURN &comment&cmd
  )

Hook_Temp_0:
  LOCAL &input_val &output_val
  ENTRY &input_val
  IF ("&cpufamily"=="MPC82XX")||("&cpufamily"=="MPC74XX")||("&cpufamily"=="MPC6XX7XX")
    &output_val=&temp_0
  ELSE
    STOP "No temp register 0 hook defined for CPU &cf_tar"
  RETURN &output_val

Hook_Temp_1:
  LOCAL &input_val &output_val
  ENTRY &input_val
  IF ("&cpufamily"=="MPC82XX")||("&cpufamily"=="MPC74XX")||("&cpufamily"=="MPC6XX7XX")
    &output_val=&temp_0+&temp_1
  ELSE
    STOP "No temp register 1 hook defined for CPU &cf_tar"
  RETURN &output_val
