これだけ安いと普段買うのがばからしくなるので、そこそこにしておいて欲しい
これだけ安いと普段買うのがばからしくなるので、そこそこにしておいて欲しい
(add-load-path "../../src/" :relative) (use npsv) ; initialize (npsv-initialize! "npsv_top") ; instancation (define inp (make-inmem-from-file "./setting/inmem.scm")) (define sinrom (make-rom-from-file "./setting/sin.scm")) (define outp (make-outmem-from-file "./setting/outmem.scm")) ; wire connection (connect inp sinrom) (connect sinrom outp) ; output (make-all-rtl "./output/rtl") (make-initialize-file inp) (make-top-testbench "./output/tb") (make-dataflow)
こんな感じでschemeを書くとVerilogを出してくれる。
データフロー図では、データ入力用のメモリと、ROM引きのsin関数、データ出力用のメモリが接続されている。データ入力用のメモリとROMのアドレスが直結できないので変換のモジュールが自動的に入る。
入力メモリに-4~+4までの値を入れて、sinを求めた結果
それっぽい。
モジュール間のプロトコルは単純で、データの有効なときはvoがH、処理が終わったらfoがHになる。これを順番に渡していくと、最後のメモリに値が書き終わったときに、最後のfoがHで終了通知になる。
後は、加算とか行列計算とかのモジュールを必要な分だけ作っていけば、複雑な計算で必要な精度の試行錯誤が楽にできそう。
extendをこのように定義した場合、lookupとupdate!を定義して、元のバージョンと比較しなさい。
(define exntend (lambda (env names values) (cons (cons names values) env)))
pass というかリナザウでやるのが辛かったので挫折。
メリットは環境の拡張が早い、デメリットは検索(と更新)が面倒。
definitial が、
(set! (env.global (cons (cons 'name valus) env.global)))
なので、definitial も変えないと整合が取れない。
(car env)で先頭を取り出して、listならextendで拡張した変数、そうじゃなかったらdefinitialで定義した変数とすればいけるが、そこを頑張る意味が無さそうなのでPASS。
作ったsin関数って、精度が悪くて使い物にならないことに気が付いた。二次の補正くらい欲しい。まあ、精度ひどくても動くところまで頑張ろう
GDG神戸のLTどうしよっかな。
evilsの最後の再起が無駄なのでなくしましょう。
修正前
(define evlis (lambda (exps env) (if (pair? exps) (let ((arg1 (evaluate (car exps) env))) (cons arg1 (evlis (cdr exps) env))) '())))
修正後
;exer 1.2 (define evlis (lambda (exps env) (let ((arg1 (evaluate (car exps) env))) (if (= (length exps) 1) (cons arg1 '()) (cons arg1 (evlis (cdr exps) env))))))
トレース機能を追加しました。
実装してから、出題の意図としては俺言語の方で追加するんじゃないかとも思いましたが、素のSchemeの方で追加できるようにしました。
テストは100点を目指すよりは合格すればOKのタイプ。
まずは、トレースON/OFFを制御する信号と、トレース対象の関数名(シンボル)を保存するためのListを宣言
(define *trace-en* #f) (define *trace-list* '())
APIっぽいの
(define trace-on (lambda () (set! *trace-en* #t))) (define trace-off (lambda () (set! *trace-en* #f))) (define trace (lambda (s) (set! *trace-list* (cons s *trace-list*))))
引数で与えられたシンボルが、トレース対象かどうかの判定関数
(define trace? (lambda (s) (and *trace-en* (member s *trace-list*))))
evaluateの中身(invoke周辺)
(let ([func (car e)] [args (evlis (cdr e) env)]) (when (trace? func) (format #t "call ~A ~A~%" func args)) (let ([result (invoke (evaluate func env) args)]) (when (trace? func) (format #t "rerurn ~A ~A result ~A ~%" func args result)) result)))]
引数が複数回評価されないように、先頭でfunc、argsに代入し、funcがトレース対象なら、呼び出し前と、呼出し後で関数名と引数、戻り値を表示していま
す。
プログラムはインタープリターに打ち込んでられないので、リストを評価するための関数も追加。長門プロンプトで、自分の処理系が出しているメッセージであることを強調しています。
(define chap1-scheme-bat (lambda (args) (dolist (s args) (format #t "YUKI.N> ~A~%" (evaluate s env.global)))))
あとはこんな感じで階乗を実行してみます。
(load "./chap1.scm") (trace-on) (trace 'fact) (chap1-scheme-bat '((set! fact (lambda (x) (if (= x 1) 1 (* (fact (- x 1)) x)))) (fact 5)))
これを実行すると、
call fact (5) call fact (4) call fact (3) call fact (2) call fact (1) rerurn fact (1) result 1 rerurn fact (2) result 2 rerurn fact (3) result 6 rerurn fact (4) result 24 rerurn fact (5) result 120 YUKI.N> 120
このように表示されます。
2年半ぶりに勉強を再開しました。
譲っていただいたLinux ZaurusでGaucheを使いながらぽちぽちと入力しています。
3回目くらいなので、比較的まっすぐに打ち込むことができました。
https://github.com/natsutan/Lisp_in_Small_Pieces/tree/master/chap1
各関数の簡単なテストもつけています。