

(in-package "CL-USER")

(defun is-addr-line (str)
  (position #\@ str))

(defun get-addr (str)
  (parse-integer (subseq str (+ 1 (position #\@ str))) :radix 16))


(defun extract-mod (val modulus)
  (multiple-value-bind (a b) (floor (floor val (expt 256 modulus)) 256)
    b))


(defun make-xi-init (ifname ofname base from-addr to-addr width select name)
  (with-open-file (fin ifname :direction :input)
    (with-open-file (fout ofname :direction :output :if-exists :supersede :if-does-not-exist :create)
      (let ((mem-map (make-array (+ 1 (- to-addr from-addr)) :initial-element 0)))
        (loop
         with addr = from-addr
         with val = nil
         with akt-line = nil
         do
         (setf akt-line (read-line fin nil nil))
         (if (null akt-line)
             (return-from nil nil))
         (when (is-addr-line akt-line)
             (setf addr (* width (get-addr akt-line)))
             (setf akt-line (read-line fin nil nil)))
         (if (null akt-line)
             (return-from nil nil))
         (setf val (parse-integer akt-line :radix base))
         (if (< addr to-addr)
             (loop for m from 0 to 3 do
                   (setf (aref mem-map (+ (- addr from-addr) m)) (extract-mod val m))))
         (setf addr (+ addr 4)))

        (format fout "//Dump of File ~a ~%//" ifname)
        (loop for i from 0 to (- to-addr from-addr 1) do
              (format fout "~2,'0X" (aref mem-map i))
              (if (= 0 (rem (+ i 1) 32))
                  (format fout "~%//"))
              finally (format fout "//~%//***~%"))
        
        (loop
         with out-line = 0
         with out-addr = 0
         with mult = 1
         with val = nil
         for addr from 0 to (- to-addr from-addr 1) by 4 do
         (setf val 
               (loop 
                with s = 0 
                for m from 3 downto 0 do 
                (setf s (+ (* 256 s) (aref mem-map (+ addr m))))
                finally return s)) 
         (loop
          for m from 0 to 3 do
          (if (/= (logand select (expt 2 m)) 0)
              (progn
                (setf out-line (+ out-line (* mult (extract-mod val m))))
                (setf out-addr (+ out-addr 1))
                (setf mult (* mult 256)))))
         (when (and (> out-addr 0) (= (rem out-addr 32) 0))
           (format fout "defparam ~a.INIT_~2,'0X = 256'h~64,'0X ;~%" name (floor (- out-addr 1) 32) out-line)
           (setf mult 1)
           (setf out-line 0)))))))
 


(defun do-defparam()
  (make-xi-init "akt-test.dump" "out0.defparam" 16 0 8192 1 1 "gldata_ram0")
  (make-xi-init "akt-test.dump" "out1.defparam" 16 0 8192 1 2 "gldata_ram1")
  (make-xi-init "akt-test.dump" "out2.defparam" 16 0 8192 1 4 "gldata_ram2")
  (make-xi-init "akt-test.dump" "out3.defparam" 16 0 8192 1 8 "gldata_ram3")

  (make-xi-init "mainmask.micdata" "mainmask.defparam" 2 0 2048 4 15 "gldata_rama")
  (make-xi-init "auxmask.micdata" "auxmask.defparam" 2 0 2048 4 15 "gldata_ramb"))
