2012-04-05 12 views
8

Tôi mới dùng vợt/sơ đồ, vì vậy tôi quyết định tìm hiểu bằng cách triển khai bộ mô phỏng cho DCPU-16, một bộ xử lý 16 bit đơn giản.Thành phần Racket/Scheme thích hợp cho mã này là gì?

Câu hỏi của tôi là: Cách tốt hơn để triển khai giải pháp của tôi là gì?

Đây là giải pháp tôi đã tấn công cùng nhau để kiểm soát sổ đăng ký của cpu. Điểm chính là cho phép các chức năng thay đổi sổ đăng ký để được xích lại với nhau. Ví dụ:

; Increment value stored in register r-id 
; returns the updated register 
; 
; Reg - the register structure 
; (reg-inc Reg 'SP) 
(define (reg-inc reg r-id) 
    (reg-write reg r-id (+ (reg-read reg r-id) 1))) 

; chain them together 
;(reg-inc (reg-inc Reg 'SP) 
;   'PC) 
; 
; returns structure with both 'SP and 'PC incremented 

Toàn bộ văn bản của giải pháp đăng ký của tôi bên dưới. My full program cũng có trên github. Có rất nhiều lặp lại logic, tôi biết có phải là một cách dễ dàng hơn:

(struct registers (A B C X Y Z I J SP PC O Pa Pb Paadr Pbadr CLK) 
    #:transparent) 

(define Reg (registers 0 0 0 0 0 0 0 0 #x10000 0 0 0 0 0 0 0)) 

(define (reg-name n) 
    (case n 
    [(0) 'A] 
    [(1) 'B] 
    [(2) 'C] 
    [(3) 'X] 
    [(4) 'Y] 
    [(5) 'Z] 
    [(6) 'I] 
    [(7) 'J] 
    [(8) 'SP] 
    [(9) 'PC] 
    [(10) 'O] 
    [(11) 'Pa] 
    [(12) 'Pb] 
    [(13) 'Paadr] 
    [(14) 'Pbadr] 
    [(15) 'CLK] 
    [else (error "Invalid register")])) 

(define (reg-id s) 
    (cond 
    [(eq? 'A s) 0] 
    [(eq? 'B s) 1] 
    [(eq? 'C s) 2] 
    [(eq? 'X s) 3] 
    [(eq? 'Y s) 4] 
    [(eq? 'Z s) 5] 
    [(eq? 'I s) 6] 
    [(eq? 'J s) 7] 
    [(eq? 'SP s) 8] 
    [(eq? 'PC s) 9] 
    [(eq? 'O s) 10] 
    [(eq? 'Pa s) 11] 
    [(eq? 'Pb s) 12] 
    [(eq? 'Paadr s) 13] 
    [(eq? 'Pbadr s) 14] 
    [(eq? 'CLK s) 15])) 

(define (reg-read reg r) 
    (if (symbol? r) 
     (reg-read reg (reg-id r)) 
     (case r 
     [(0) (registers-A reg)] 
     [(1) (registers-B reg)] 
     [(2) (registers-C reg)] 
     [(3) (registers-X reg)] 
     [(4) (registers-Y reg)] 
     [(5) (registers-Z reg)] 
     [(6) (registers-I reg)] 
     [(7) (registers-J reg)] 
     [(8) (registers-SP reg)] 
     [(9) (registers-PC reg)] 
     [(10) (registers-O reg)] 
     [(11) (registers-Pa reg)] 
     [(12) (registers-Pb reg)] 
     [(13) (registers-Paadr reg)] 
     [(14) (registers-Pbadr reg)] 
     [(15) (registers-CLK reg)] 
     [else (error "Invalid register")]))) 

(define (reg-write reg r val) 
    (if (symbol? r) 
     (reg-write reg (reg-id r) val) 
     (let ([mask-val (bitwise-and val #xffff)]) 
     (case r 
      [(0) (struct-copy registers reg [A mask-val])] 
      [(1) (struct-copy registers reg [B mask-val])] 
      [(2) (struct-copy registers reg [C mask-val])] 
      [(3) (struct-copy registers reg [X mask-val])] 
      [(4) (struct-copy registers reg [Y mask-val])] 
      [(5) (struct-copy registers reg [Z mask-val])] 
      [(6) (struct-copy registers reg [I mask-val])] 
      [(7) (struct-copy registers reg [J mask-val])] 
      [(8) (struct-copy registers reg [SP mask-val])] 
      [(9) (struct-copy registers reg [PC mask-val])] 
      [(10) (struct-copy registers reg [O mask-val])] 
      [(11) (struct-copy registers reg [Pa mask-val])] 
      [(12) (struct-copy registers reg [Pb mask-val])] 
      [(13) (struct-copy registers reg [Paadr mask-val])] 
      [(14) (struct-copy registers reg [Pbadr mask-val])] 
      [(15) (struct-copy registers reg [CLK mask-val])] 
      [else (error "Invalid register")])))) 

Cập nhật:

Nhờ sugestions oobviat của tôi đã refactored sử dụng danh sách. Phần khó khăn duy nhất là cập nhật một giá trị trong danh sách. Tôi đã viết một thủ tục cho bản đồ đó sẽ cập nhật thanh ghi mong muốn và để lại những người khác với giá trị ban đầu của họ:

;; a-list of registers and initial values 
(define (build-reg) 
    '((A . 0) (B . 0)  (C . 0)  (X . 0) 
    (Y . 0) (Z . 0)  (I . 0)  (J . 0) 
    (SP . 0) (PC . 0) (O . 0)  (Pa . 0) 
    (Pb . 0) (Paadr . 0) (Pbadr . 0) (CLK . 0))) 

(define *REF-REG* (build-reg)) ; used to determine structure 

(define (reg-name n) 
    (if (symbol? n) 
     n 
     (car (list-ref *REF-REG* n)))) 

(define (reg-id s) 
    (- (length *REF-REG*) 
    (length (memf (lambda (arg) 
        (eq? s (car arg))) 
        *REF-REG*)))) 

(define (reg-write reg r val) 
    (let ([r-name (reg-name r)]) 
    (define (reg-write-helper entry) 
     (if (eq? r-name 
       (car entry)) 
      (cons r-name val) 
      entry)) 
    (map reg-write-helper reg))) 

(define (reg-read reg r) 
    (cdr (assoc (reg-name r) reg))) 
+0

Cấu trúc không có thủ tục nội tâm không? Tôi chắc chắn nó. – leppie

+0

@leppie, cấu trúc không có tên của chúng trong thông tin nội tâm. –

Trả lời

2

này đã không được viết bằng vợt, vì vậy nó không thể chạy cho bạn như là .. nếu nó ném lỗi cố gắng chỉ định loại mã R5RS ở đầu tệp. Để đơn giản, tôi sẽ làm một cái gì đó như thế này bằng cách sử dụng một danh sách chứ không phải là cấu trúc.

;; a-list of registers and initial values 
(define *reg* 
    '((A . 0) (B . 0) (C . 0) (X . 0) (Y . 0) (Z . 0) 
    (I . 0) (J . 0) (SP . #X10000) (PC . 0) (O . 0) 
    (Pa . 0) (Pb . 0) (Paadr . 0) (Pbadr . 0) (CLK . 0))) 

(define (reg-write register val) 
    (set-cdr! (assoc register *reg*) val) ;write new value to register 
    val) ; return newly written value 

(define (reg-read register) 
    (cdr (assoc register *reg*))) 

(define (reg-inc register) 
    (reg-write register (+ 1 (reg-read register)))) 

;; to do many operations 
;; input: a list of registers 
;; EX: '(a b x) 
(define (do-incs registers) 
    (if (null? registers) 
     'done  ; return something when the incs are done 
     (begin  ; lets you evaluate multiple expressions since `if` doesn't   
     (reg-inc (car registers)) 
     (do-incs (cdr registers))))) 

Tôi giả định rằng Racket có sẵn như assoc trả về danh sách thích hợp từ danh sách. Ngoài ra, lưu ý rằng *reg* được định nghĩa là biến toàn cầu trong trường hợp này để chúng tôi có thể xác định nó một lần sau đó sử dụng set-cdr! để ghi giá trị cho nó.

cuối cùng, điều này có thể làm những điều lạ với thanh ghi SP của bạn. Đề án của tôi thấy nó là 65536 .. nếu điều đó không đúng, bạn có thể phải thêm một số if đến reg-writereg-read để đảm bảo bạn đang nhận được các giá trị phù hợp tại đó.

<EDIT> Vì vậy, tôi đọc một chút về thủ tục Racket, và mã này gần như chắc chắn sẽ không chạy trong Racket bình thường vì họ dường như có cả hai cặp có thể thay đổi và không thể thay đổi. Những thay đổi bạn sẽ phải thực hiện nếu bạn muốn chạy điều này dưới Racket và không R5RS như sau:

Thay vì chỉ sử dụng danh sách được trích dẫn, bạn có thể cần phải tạo danh sách đăng ký với các nhà xây dựng danh sách/cặp có thể thay đổi (define *reg* (mlist (mcons 'A 0) (mcons 'B 0) ...).

Thay vì sử dụng set-cdr! phiên bản vợt là set-mcdr! và chỉ hoạt động trên các cặp có thể thay đổi. </EDIT>

+0

[Có.] (Http://docs.racket-lang.org/reference/pairs.html# (def._ ((lib._racket/private/list..rkt) ._assoc))) – Taymon

+0

Vâng. figured nó là một giả định khá an toàn. – oobivat

+0

Tôi muốn viết điều này mà không cần sử dụng bộ, buộc bản thân phải suy nghĩ khác đi. Giải pháp danh sách của bạn đã truyền cảm hứng cho triển khai mới của tôi. –

Các vấn đề liên quan