2012-04-05 16 views
8

मैं रैकेट/योजना के लिए नया हूं, इसलिए मैंने DCPU-16, एक साधारण 16 बिट प्रोसेसर के लिए एक एमुलेटर को लागू करके सीखने का निर्णय लिया।इस कोड के लिए उपयुक्त रैकेट/योजना मुहावरे क्या है?

मेरा प्रश्न इस प्रकार है: मेरे समाधान को लागू करने का एक बेहतर तरीका क्या है?

यह वह समाधान है जिसे मैंने सीपीयू के रजिस्टरों को नियंत्रित करने के लिए एक साथ हैक किया था। मुख्य बिंदु उन कार्यों को अनुमति देना था जो एक रजिस्टर को संशोधित करने के लिए संशोधित करते थे। उदाहरण के लिए:

; 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 

मेरे रजिस्टर समाधान का पूरा पाठ नीचे है। My full program भी जिथूब पर है। वहाँ इतना दोहराया है तर्क, मैं जानता हूँ कि एक आसान तरीका होना चाहिए:

(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")])))) 

अद्यतन:

oobviat के sugestions के लिए धन्यवाद मैं सूचियों का उपयोग पुनर्संशोधित गए हैं। एकमात्र मुश्किल हिस्सा सूची में एक मूल्य अद्यतन कर रहा था। मैं नक्शे के लिए एक प्रक्रिया है जो वांछित रजिस्टर को अद्यतन करेगा और उनके मूल मूल्य के साथ दूसरों को छोड़ लिखा है:

;; 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

क्या structs के पास कोई आत्मनिरीक्षण प्रक्रिया नहीं है? मुझे यकीन है कि यह करता है। – leppie

+0

@leppie, structs आत्मनिरीक्षण जानकारी में उनके नाम नहीं है। –

उत्तर

2

इस रैकेट में नहीं लिखा गया था, तो यह आप के लिए नहीं चल सकते हैं के रूप में .. अगर यह फेंकता त्रुटियां फ़ाइल के शीर्ष पर R5RS कोड प्रकार निर्दिष्ट करने का प्रयास करें। सादगी के लिए, मैं structs की बजाय एक सूची का उपयोग कर ऐसा कुछ करूँगा।

;; 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))))) 

मुझे लगता है कि रैकेट है assoc है कि एक-सूची में से उचित सूची लौटाती है की तरह में एक निर्मित यह सोचते हैं रहा हूँ। साथ ही, ध्यान दें कि *reg* को इस मामले में वैश्विक चर के रूप में परिभाषित किया गया है ताकि हम इसे एक बार परिभाषित कर सकें, फिर set-cdr! का उपयोग मूल्यों को लिखने के लिए करें।

आखिरकार, यह आपके SP रजिस्टर में अजीब चीजें कर सकता है। मेरी योजना इसे 65536 के रूप में देखती है .. यदि यह सही नहीं है, तो आपको यह सुनिश्चित करने के लिए कि आपको सही मूल्य मिल रहे हैं, आपको if से reg-write और reg-read जोड़ना पड़ सकता है।

<EDIT> तो, मैं रैकेट प्रक्रियाओं पर थोड़ा सा पढ़ता हूं, और यह कोड लगभग निश्चित रूप से सामान्य रैकेट में नहीं चलेगा क्योंकि उनके पास स्पष्ट रूप से दोनों परिवर्तनीय और गैर-परिवर्तनीय जोड़े हैं। यदि आप रैकेट के तहत इसे चलाने के लिए चाहते हैं तो आपको बदलाव करना होगा और आर 5 आरएस निम्नानुसार नहीं हैं:

केवल उद्धृत सूची का उपयोग करने के बजाय आपको संभवतः उत्परिवर्तनीय सूची/जोड़ी रचनाकारों के साथ रजिस्टरों की अपनी सूची बनाने की आवश्यकता होगी (define *reg* (mlist (mcons 'A 0) (mcons 'B 0) ...)

set-cdr! का उपयोग करने के बजाय रैकेट संस्करण set-mcdr! है और केवल परिवर्तनीय जोड़े पर काम करता है। </EDIT>

+0

[यह करता है।] (Http://docs.racket-lang.org/reference/pairs.html# (def._ ((lib._racket/private/list..rkt) ._assoc)) – Taymon

+0

हाँ। यह लगा कि यह एक सुंदर सुरक्षित धारणा थी। – oobivat

+0

मैं इसे अलग-अलग सोचने के लिए मजबूर करने के लिए, सेट के उपयोग के बिना इसे लिखना चाहता था। आपकी सूची समाधान ने मेरे नए कार्यान्वयन को प्रेरित किया। –

संबंधित मुद्दे