X-Git-Url: http://git.ieval.ro/?a=blobdiff_plain;f=lib%2FApp%2FScheme79asm.pm;h=5aebe08689da7b303fc85016d414f0a16d8ae910;hb=0edb4b34e85aceb436bfc91748338a4155c881e5;hp=e0bec36c64c32388335bd625fbacf63b36c6b0ed;hpb=4a9c3fa907cbf1473f82ddeda2186a0fca3959fe;p=app-scheme79asm.git diff --git a/lib/App/Scheme79asm.pm b/lib/App/Scheme79asm.pm index e0bec36..5aebe08 100644 --- a/lib/App/Scheme79asm.pm +++ b/lib/App/Scheme79asm.pm @@ -8,7 +8,7 @@ use Data::Dumper qw/Dumper/; use Data::SExpression qw/consp scalarp/; use Scalar::Util qw/looks_like_number/; -our $VERSION = '0.001'; +our $VERSION = '0.002'; our %TYPES = ( LIST => 0, @@ -58,6 +58,8 @@ sub process { $addr = $self->process($addr) if ref $addr eq 'ARRAY'; die 'Addr of toplevel is not atom: ', Dumper($addr), "\n" unless scalarp($addr); + my ($comment_type, $comment_addr) = ($type, $addr); + unless (looks_like_number $addr) { # is symbol unless (exists $self->{symbols}{$addr}) { $self->{symbols}{$addr} = $self->{nsymbols}; @@ -83,6 +85,7 @@ sub process { $location = $self->{freeptr} } $self->{memory}[$location] = $result; + $self->{comment}[$location] = "$comment_type $comment_addr"; $location } @@ -101,6 +104,7 @@ sub parse { sub finish { my ($self) = @_; $self->{memory}[5] = $self->{memory}[$self->{freeptr}]; + $self->{comment}[5] = $self->{comment}[$self->{freeptr}]; $self->{memory}[4] = $self->{freeptr}; delete $self->{memory}[$self->{freeptr}] } @@ -114,6 +118,7 @@ sub new { $args{symbols}{NIL} = 0; $args{symbols}{T} = 1; $args{nsymbols} = 2; + $args{comment} = ['(cdr part of NIL)', '(car part of NIL)', '(cdr part of T)', '(car part of T)', '(free storage pointer)', '', '(result of computation)']; bless \%args, $class } @@ -122,14 +127,19 @@ sub print { $fh //= \*STDOUT; my $bits = $self->{type_bits} + $self->{addr_bits}; + my $index_length = length $#{$self->{memory}}; + my $index_format = '%' . $index_length . 'd'; for my $index (0 .. $#{$self->{memory}}) { my $val = $self->{memory}[$index]; + my $comment = $self->{comment}[$index]; if ($index == 4) { $val = "${bits}'d$val" } else { $val = $val ? sprintf "%d'b%0${bits}b", $bits, $val : '0'; } - say $fh "mem[$index] <= $val;" + my $spaces = ' ' x ($bits + 5 - (length $val)); + $index = sprintf $index_format, $index; + say $fh "mem[$index] <= $val;$spaces // $comment" } } @@ -153,25 +163,154 @@ App::Scheme79asm - assemble sexp to Verilog ROM for SIMPLE processor use App::Scheme79asm; my $asm = App::Scheme79asm->new(type_bits => 3, addr_bits => 5); - $asm->parse_and_print('(number . 70)'); + $asm->parse_and_print('(number 70)'); =head1 DESCRIPTION -B this module does not do much at the moment. - SIMPLE is a LISP processor defined in the 1979 B paper by Steele and Sussman. The SIMPLE processor expects input in a particular tagged-pointer format. This module takes a string containing a sequence of -S-expressions of the form C<(tag . value)> representing a tagged -pointer. Here the tag is either a number or one of several predefined -values (see the source for a full list), and the value is either a -number or another tagged pointer. These values are laid out in memory -and a block of verilog code assigning the memory contents to an array -named C is printed. - -More documentation and features to follow. +S-expressions. Each S-expression is a list of one of three types: + +C<(tag value)>, for example C<(symbol nil)>, represents a value to be +put in memory (for example a number, or a symbol, or a variable +reference). + +C<(tag list)>, where C is of one of these three types, +represents a tagged pointer. In this case, C is (recursively) +laid out in memory as per these rules, and a pointer to that location +(and tagged C) is put somewhere in memory. + +C<(tag list1 list2)>, where C and C are of one of these +three types (not necessarily the same type). In this case, C +and C are (recursively) laid out in memory such that C +is at position X and C is at position X+1, and a pointer of +type tag and value X is put somewhere in memory. + +After this process the very last pointer placed in memory is moved to +the special location 5 (which is where SIMPLE expects to find the +expression to be evaluated). + +In normal use a single S-expression will be supplied, representing an +entire program. + +The C is either a number, a type, or a primitive. +The available types are: + +=over + +=item LIST + +=item SYMBOL (syn. NUMBER) + +=item VAR (syn. VARIABLE) + +=item CLOSURE + +=item PROC (syn. PROCEDURE) + +=item IF (syn. COND, CONDITIONAL) + +=item CALL + +=item QUOTE (syn. QUOTED) + +=back + +The available primitives are: + +=over + +=item MORE + +=item CAR + +=item CDR + +=item CONS + +=item ATOM + +=item PROGN + +=item MAKELIST + +=item FUNCALL + +=back + +The following methods are available: + +=over + +=item App::Scheme79asm->B([key => value, key => value, ...]) + +Create a new assembler object. Takes a list of keys and values, here +are the possible keys: + +=over + +=item type_bits + +=item address_bits + +A word is made of a type and an address, with the type occupying the +most significant C (default 3) bits, and the address +occupying the least significant C (default 8) bits. +Therefore the word size is C (default 13). + +=item freeptr + +A pointer to the last used byte in memory (default 6). The program +will be laid out starting with location C. + +=item memory + +The initial contents of the memory. Note that locations 4, 5, 6 will +be overwritten, as will every location larger than the value of +C. + +=item comment + +The initial comments for memory entries. C<< $comment->[$i] >> is the +comment for C<< $memory->[$i] >>. + +=item symbols + +The initial symbol map, as a hashref from symbol name to the index of +that symbol. Defaults to C<< {NIL => 0, T => 1} >>. + +=item nsymbols + +The number of distinct symbols in the initial symbols map (default 2). + +=back + +=item $asm->B(I<$string>) + +Parse a sequence of S-expressions and lay it out in memory. +Can be called multiple times to lay out multiple sequences of +S-expressions one after another. + +=item $asm->B + +Move the last pointer to position 5, and put the free pointer at +position 4. After all sequences of S-expressions have been given to +B, this method should be called. + +=item $asm->B([I<$fh>]) + +Print a block of Verilog code assigning the memory contents to an +array named C to the given filehandle (default STDOUT). + +=item $asm->B(I<$string>[, I<$fh>]) + +Convenience method that calls B($string), B, and then +B($fh). + +=back =head1 SEE ALSO