Compare commits
No commits in common. "251120d54b811b4d5a6a68daa465b1788d231fe1" and "0aef21a9495920a2d942dc33e97bb7c51487a24d" have entirely different histories.
251120d54b
...
0aef21a949
@ -19,8 +19,6 @@
|
|||||||
has-duplicates? find-duplicates
|
has-duplicates? find-duplicates
|
||||||
insert-between
|
insert-between
|
||||||
string-replace-text
|
string-replace-text
|
||||||
string-split-trim
|
|
||||||
get-word
|
|
||||||
substitute
|
substitute
|
||||||
read-template
|
read-template
|
||||||
|
|
||||||
@ -219,22 +217,3 @@
|
|||||||
(map (lambda (str)
|
(map (lambda (str)
|
||||||
(substitute str template-format subst-list))
|
(substitute str template-format subst-list))
|
||||||
ls)))
|
ls)))
|
||||||
|
|
||||||
;;; Split string and remove empty itemes
|
|
||||||
(define (string-split-trim str pred?)
|
|
||||||
(remove string-null?
|
|
||||||
(string-split str pred?)))
|
|
||||||
|
|
||||||
;;; Get word delimited by pred? from port
|
|
||||||
(define* (get-word port #:optional (pred? char-whitespace?))
|
|
||||||
(let get-word-rec ((chlist '()))
|
|
||||||
(let ((c (get-char port)))
|
|
||||||
(if (eof-object? c)
|
|
||||||
(if (null? chlist)
|
|
||||||
#f
|
|
||||||
(list->string (reverse chlist)))
|
|
||||||
(if (pred? c)
|
|
||||||
(if (null? chlist)
|
|
||||||
(get-word-rec chlist)
|
|
||||||
(list->string (reverse chlist)))
|
|
||||||
(get-word-rec (cons c chlist)))))))
|
|
||||||
|
|||||||
332
embddr/vcd.scm
332
embddr/vcd.scm
@ -1,332 +0,0 @@
|
|||||||
(define-module (embddr vcd))
|
|
||||||
|
|
||||||
(import (srfi srfi-1) ; Lists
|
|
||||||
(srfi srfi-9) ; Records
|
|
||||||
(srfi srfi-11) ; Values
|
|
||||||
(srfi srfi-26) ; Cut
|
|
||||||
(srfi srfi-28) ; Simple format
|
|
||||||
(srfi srfi-34) ; Exceptions
|
|
||||||
(srfi srfi-69) ; Hash tables
|
|
||||||
(ice-9 textual-ports))
|
|
||||||
|
|
||||||
(import
|
|
||||||
(ice-9 pretty-print)
|
|
||||||
(statprof))
|
|
||||||
|
|
||||||
(import (embddr common))
|
|
||||||
|
|
||||||
(export vcd-parse
|
|
||||||
(signal-scope . vcd-signal-scope)
|
|
||||||
(signal-name . vcd-signal-name)
|
|
||||||
(signal-type . vcd-signal-type)
|
|
||||||
(signal-size . vcd-signal-size)
|
|
||||||
(signal-get . vcd-signal-get)
|
|
||||||
vcd-binary->hex)
|
|
||||||
|
|
||||||
;;;
|
|
||||||
;;; VCD data structure
|
|
||||||
;;;
|
|
||||||
(define-record-type <vcd>
|
|
||||||
(vcd-new timescale timestamps signals)
|
|
||||||
vcd?
|
|
||||||
(timescale vcd-timescale)
|
|
||||||
(timestamps vcd-tstamps)
|
|
||||||
(signals vcd-signals))
|
|
||||||
|
|
||||||
;;;
|
|
||||||
;;; Signal representation structure
|
|
||||||
;;;
|
|
||||||
(define-record-type <signal>
|
|
||||||
(signal-new scope name type size value)
|
|
||||||
signal?
|
|
||||||
(scope signal-scope)
|
|
||||||
(name signal-name)
|
|
||||||
(type signal-type)
|
|
||||||
(size signal-size)
|
|
||||||
(value signal-get signal-set!))
|
|
||||||
|
|
||||||
;;; Add sample to signal values list
|
|
||||||
(define (signal-add! sig value)
|
|
||||||
(signal-set! sig (cons value (signal-get sig))))
|
|
||||||
|
|
||||||
;;;
|
|
||||||
;;; Parse timescale value (eg: 1ps, 100ns etc)
|
|
||||||
;;; Returns value in ns
|
|
||||||
;;;
|
|
||||||
(define (parse-timescale ts)
|
|
||||||
(let ((dim-idx (string-skip ts char-numeric?)))
|
|
||||||
(if dim-idx
|
|
||||||
(let* ((n (string->number (substring ts 0 dim-idx)))
|
|
||||||
(unit (substring ts dim-idx))
|
|
||||||
(k (assoc unit '(("s" 1e9) ("ms" 1e6) ("us" 1e3) ("ns" 1) ("ps" 1e-3) (fs 1e-6)))))
|
|
||||||
(if k
|
|
||||||
(* n (cadr k))
|
|
||||||
(raise `(vcd-syntax-error
|
|
||||||
,(format "Unknown timescale unit '~a'" unit)))))
|
|
||||||
(raise `(vcd-syntax-error
|
|
||||||
,(format "Wrong timescale '~a'" ts))))))
|
|
||||||
|
|
||||||
;;;
|
|
||||||
;;; Parse and extend binary value
|
|
||||||
;;;
|
|
||||||
(define (parse-binary-value str width)
|
|
||||||
(let ((len (string-length str)))
|
|
||||||
(cond
|
|
||||||
((zero? len)
|
|
||||||
(raise `(vcd-syntax-error "Empty binary value")))
|
|
||||||
|
|
||||||
((> len width)
|
|
||||||
(raise `(vcd-syntax-error
|
|
||||||
,(format "Binary value (~a) length > signal width (~a)" str width))))
|
|
||||||
|
|
||||||
;; Extend shorter
|
|
||||||
((< len width)
|
|
||||||
(string-append
|
|
||||||
(make-string
|
|
||||||
(- width len)
|
|
||||||
(let ((h (string-ref str 0)))
|
|
||||||
(if (char-numeric? h) #\0 h)))
|
|
||||||
str))
|
|
||||||
|
|
||||||
(else str))))
|
|
||||||
|
|
||||||
;;;
|
|
||||||
;;; Parse real value
|
|
||||||
;;;
|
|
||||||
(define (parse-real-value str unused) str)
|
|
||||||
|
|
||||||
;;;
|
|
||||||
;;; Get VCD tag as ($keyword ... $end) as words list without $end
|
|
||||||
;;;
|
|
||||||
(define* (vcd-get-command port)
|
|
||||||
(let get-cmd-rec ((wlist '()))
|
|
||||||
(let ((w (get-word port)))
|
|
||||||
(if (not w)
|
|
||||||
(if (null? wlist)
|
|
||||||
#f
|
|
||||||
(reverse wlist))
|
|
||||||
(if (null? wlist)
|
|
||||||
(if (or (equal? w "$comment")
|
|
||||||
(equal? w "$date")
|
|
||||||
(equal? w "$enddefinitions")
|
|
||||||
(equal? w "$scope")
|
|
||||||
(equal? w "$timescale")
|
|
||||||
(equal? w "$upscope")
|
|
||||||
(equal? w "$var")
|
|
||||||
(equal? w "$version"))
|
|
||||||
(get-cmd-rec `(,w))
|
|
||||||
(raise `(vcd-syntax-error
|
|
||||||
,(format "Unknown declaration keyword '~a'" w))))
|
|
||||||
(if (equal? w "$end")
|
|
||||||
(reverse wlist)
|
|
||||||
(get-cmd-rec (cons w wlist))))))))
|
|
||||||
|
|
||||||
;;;
|
|
||||||
;;; Parse VCD header
|
|
||||||
;;; Returns values of timescale and association list (tag . (<signal> ...))
|
|
||||||
;;;
|
|
||||||
(define (read-header port)
|
|
||||||
(let next-cmd ((timescale #f)
|
|
||||||
(scope '())
|
|
||||||
(tags+signals '()))
|
|
||||||
(let ((cmd (vcd-get-command port)))
|
|
||||||
(if (not cmd)
|
|
||||||
(if timescale
|
|
||||||
(values timescale tags+signals)
|
|
||||||
(raise `(vcd-syntax-error "Timescale is not defined")))
|
|
||||||
(let ((name (first cmd)))
|
|
||||||
(cond
|
|
||||||
((string-ci= name "$timescale")
|
|
||||||
(next-cmd (parse-timescale (second cmd)) scope tags+signals))
|
|
||||||
|
|
||||||
((string-ci= name "$scope")
|
|
||||||
(next-cmd timescale (cons (third cmd) scope) tags+signals))
|
|
||||||
|
|
||||||
((string-ci= name "$var")
|
|
||||||
(let ((type (cond
|
|
||||||
((or (equal? "real" (second cmd))
|
|
||||||
(equal? "realtime" (second cmd))) 'real)
|
|
||||||
((equal? "event" (second cmd)) 'event)
|
|
||||||
(else 'bits)))
|
|
||||||
(width (string->number (third cmd)))
|
|
||||||
(tag (fourth cmd))
|
|
||||||
(vname (string-concatenate
|
|
||||||
(insert-between
|
|
||||||
(cddddr cmd) " "))))
|
|
||||||
(next-cmd timescale scope
|
|
||||||
(let ((tag+sig (assoc tag tags+signals))
|
|
||||||
(sig (signal-new (reverse scope)
|
|
||||||
vname type width '())))
|
|
||||||
(if tag+sig
|
|
||||||
(begin
|
|
||||||
(set-cdr! tag+sig (cons sig (cdr tag+sig)))
|
|
||||||
tags+signals)
|
|
||||||
(cons (cons tag `(,sig)) tags+signals))))))
|
|
||||||
|
|
||||||
((string-ci= "$upscope" (first cmd))
|
|
||||||
(next-cmd timescale (cdr scope) tags+signals))
|
|
||||||
|
|
||||||
((string-ci= "$enddefinitions" (first cmd))
|
|
||||||
(if (not timescale)
|
|
||||||
(raise '(vcd-syntax-error "Timescale is not defined"))
|
|
||||||
(values timescale tags+signals)))
|
|
||||||
|
|
||||||
(else (next-cmd timescale scope tags+signals))))))))
|
|
||||||
|
|
||||||
;;;
|
|
||||||
;;; Read data block and return list of lists (time changes ..)
|
|
||||||
;;;
|
|
||||||
(define (read-data port)
|
|
||||||
(let read-rec ((samples '())
|
|
||||||
(time #f)
|
|
||||||
(changes '()))
|
|
||||||
(let ((line (get-line port)))
|
|
||||||
(if (eof-object? line)
|
|
||||||
(reverse
|
|
||||||
(if (and time (not (null? changes)))
|
|
||||||
(cons (cons time changes) samples)
|
|
||||||
samples))
|
|
||||||
(let ((line (string-trim-both line)))
|
|
||||||
(cond
|
|
||||||
((or (string-null? line)
|
|
||||||
(equal? (string-ref line 0) #\$))
|
|
||||||
(read-rec samples time changes))
|
|
||||||
|
|
||||||
((equal? (string-ref line 0) #\#)
|
|
||||||
(read-rec
|
|
||||||
(if (and time (not (null? changes)))
|
|
||||||
(cons (cons time changes) samples)
|
|
||||||
samples)
|
|
||||||
(let ((time (string->number (substring line 1))))
|
|
||||||
(if time
|
|
||||||
time
|
|
||||||
(raise `(vcd-syntsx-error "Bad time format '~a'" line))))
|
|
||||||
'()))
|
|
||||||
|
|
||||||
(else
|
|
||||||
(read-rec samples time (cons line changes)))))))))
|
|
||||||
|
|
||||||
;;;
|
|
||||||
;;; Parse VCD data block
|
|
||||||
;;; Returns <vcd> record
|
|
||||||
;;;
|
|
||||||
(define (parse-data samples timescale tags+signals)
|
|
||||||
(let* ((samples-count (length samples))
|
|
||||||
(tags+signals-ht (alist->hash-table tags+signals)))
|
|
||||||
|
|
||||||
(for-each
|
|
||||||
(lambda (sample)
|
|
||||||
(let ((time (car sample)))
|
|
||||||
(for-each
|
|
||||||
(lambda (line)
|
|
||||||
(let ((c0 (string-ref line 0))
|
|
||||||
(rest (substring line 1)))
|
|
||||||
;; (display (format "-- c0:'~a' rest:'~a'\n" c0 rest))
|
|
||||||
(let-values
|
|
||||||
(((parse-value tag value)
|
|
||||||
(cond
|
|
||||||
;; Scalar value
|
|
||||||
((or (equal? c0 #\0)
|
|
||||||
(equal? c0 #\1)
|
|
||||||
(char-ci=? c0 #\x)
|
|
||||||
(char-ci=? c0 #\z))
|
|
||||||
(values parse-binary-value
|
|
||||||
rest
|
|
||||||
(string (char-downcase c0))))
|
|
||||||
|
|
||||||
;; Binary or real value
|
|
||||||
((or (char-ci=? c0 #\b)
|
|
||||||
(char-ci=? c0 #\r))
|
|
||||||
|
|
||||||
;; Fast but unsafe
|
|
||||||
(let ((val-idx (string-index rest #\space)))
|
|
||||||
(if val-idx
|
|
||||||
(let ((value (substring rest 0 val-idx))
|
|
||||||
(tag (substring rest (+ val-idx 1))))
|
|
||||||
(values (if (char-ci=? c0 #\b)
|
|
||||||
parse-binary-value
|
|
||||||
parse-real-value)
|
|
||||||
tag
|
|
||||||
value))
|
|
||||||
(raise `(vcd-syntax-error
|
|
||||||
,(format "Bad value change string '~a'" line)))))
|
|
||||||
|
|
||||||
;; Slow but safety
|
|
||||||
;; (let ((ss (string-split-trim rest char-whitespace?)))
|
|
||||||
;; (if (= (length ss) 2)
|
|
||||||
;; (let ((value (first ss))
|
|
||||||
;; (tag (second ss)))
|
|
||||||
;; (values (if (char-ci=? c0 #\b)
|
|
||||||
;; parse-binary-value
|
|
||||||
;; parse-real-value)
|
|
||||||
;; tag
|
|
||||||
;; value))
|
|
||||||
;; (raise `(vcd-syntax-error
|
|
||||||
;; ,(format "Bad value change string '~a'" line)))))
|
|
||||||
))))
|
|
||||||
|
|
||||||
(let ((sigs (hash-table-ref/default tags+signals-ht tag #f)))
|
|
||||||
(unless (null? sigs)
|
|
||||||
(for-each
|
|
||||||
(lambda (sig)
|
|
||||||
(signal-add!
|
|
||||||
sig
|
|
||||||
(cons time (parse-value value (signal-size sig)))))
|
|
||||||
sigs))))))
|
|
||||||
(cdr sample))))
|
|
||||||
samples)
|
|
||||||
|
|
||||||
(vcd-new timescale
|
|
||||||
(map car samples)
|
|
||||||
(let ((signals (fold (lambda (tag+sig out)
|
|
||||||
(append (cdr tag+sig) out))
|
|
||||||
'() tags+signals))
|
|
||||||
(last-time (car (last samples))))
|
|
||||||
(map (lambda (sig)
|
|
||||||
(signal-set! sig (reverse (signal-get sig)))
|
|
||||||
sig)
|
|
||||||
signals)))))
|
|
||||||
|
|
||||||
;;;
|
|
||||||
;;; Parse whole VCD
|
|
||||||
;;; Returns list of time stamps and list of lists (<signal> valuse ...)
|
|
||||||
;;;
|
|
||||||
(define (vcd-parse port)
|
|
||||||
(call-with-values
|
|
||||||
(lambda () (read-header port))
|
|
||||||
(cut parse-data
|
|
||||||
(read-data port)
|
|
||||||
<...>)))
|
|
||||||
|
|
||||||
;;;
|
|
||||||
;;; Convert 4-state binary string to hex
|
|
||||||
;;;
|
|
||||||
(define (vcd-binary->hex binstr)
|
|
||||||
(string-concatenate
|
|
||||||
(map
|
|
||||||
(lambda (quad)
|
|
||||||
(if (string-every char-numeric? quad)
|
|
||||||
(number->string
|
|
||||||
(string->number quad 2)
|
|
||||||
16)
|
|
||||||
(if (string-every (cut char-ci=? #\z <>) quad)
|
|
||||||
"z"
|
|
||||||
"x")))
|
|
||||||
(let split-by-quad ((str (string-reverse binstr))
|
|
||||||
(quads '()))
|
|
||||||
(cond
|
|
||||||
((string-null? str) quads)
|
|
||||||
((<= (string-length str) 4)
|
|
||||||
(cons (string-append
|
|
||||||
(make-string
|
|
||||||
(- 4 (string-length str))
|
|
||||||
(let ((h (string-ref str 0)))
|
|
||||||
(if (char-numeric? h) #\0 h)))
|
|
||||||
(string-reverse str))
|
|
||||||
quads))
|
|
||||||
(else
|
|
||||||
(split-by-quad
|
|
||||||
(string-drop str 4)
|
|
||||||
(cons
|
|
||||||
(string-reverse
|
|
||||||
(string-take str 4)) quads))))))))
|
|
||||||
Loading…
x
Reference in New Issue
Block a user