Make it work
[clump.git] / asm.pm
diff --git a/asm.pm b/asm.pm
index 269b8d1d49d62963131325ce32f42e95e1e0f3ca..1b6dc8ad82e0d98ad48dd0583098eb8279979a7b 100644 (file)
--- a/asm.pm
+++ b/asm.pm
@@ -36,8 +36,8 @@ my $port;
 
 
 use parent qw/Exporter/;
-our @EXPORT = qw/loada loadb store write_verilog alu_select_a alu_select_b alu_select_f alu_zero flag_zero flag_news alu_xor alu_xnor alu_or alu_of_function aluc_add alus_add aluc_addAF alus_addAF alu2 alu3 add addC loadi storei ledm ledi route/;
-our @EXPORT_OK = qw/loada loadb store write_verilog alu_select_a alu_select_b alu_select_f alu_zero flag_zero flag_news  alu_xor alu_xnor alu_or alu_of_function aluc_add alus_add aluc_addAF alus_addAF alu2 alu3 add addC loadi storei ledm ledi route/;
+our @EXPORT = qw/loada loadb store write_verilog alu_select_a alu_select_b alu_select_f alu_zero flag_zero flag_news alu_xor alu_xnor alu_or alu_of_function aluc_add alus_add aluc_addAF alus_addAF alu2 alu3 add addC loadi storei ledm ledi route chip_select/;
+our @EXPORT_OK = qw/loada loadb store write_verilog alu_select_a alu_select_b alu_select_f alu_zero flag_zero flag_news  alu_xor alu_xnor alu_or alu_of_function aluc_add alus_add aluc_addAF alus_addAF alu2 alu3 add addC loadi storei ledm ledi route chip_select/;
 
 use File::Slurp::Tiny 'write_file';
 
@@ -70,20 +70,30 @@ sub send__ {
 
 my $rom_cnt = 0;
 
+# by default instructions are for all 4 chips to execute
+our $CS = 0xF;
+
 sub send_ {
        my ($cmd) = @_;
        my %cmd = %$cmd;
+       my $op_cs = $cmd{op} + ($CS << 4);
 
-       my $binary = pack 'vCC', @cmd{qw/I mem_addr op/}; # we ignore CS for now
+       my $binary = pack 'vCC', $cmd{I}, $cmd{mem_addr}, $op_cs;
        my $hex = reverse unpack 'h*', $binary;
-       say "$rom_cnt: data <= 32'h$hex;";
+       #       say "$rom_cnt: data <= 32'h$hex;";
+       say $hex;
        $rom_cnt++;
 }
 
+sub chip_select {
+       my ($new_cs, $sub) = @_;
+       local $CS = $new_cs;
+       $sub->();
+}
 
 sub nop {
        send_
-         { I => 0, mem_addr => 0, op => OP_NOP, CS => 0 }
+         { I => 0, mem_addr => 0, op => OP_NOP }
   }
 
 sub loada {
@@ -93,7 +103,7 @@ sub loada {
        $I |= $bsel << 4;
        $I |= $aluc << 5;
        send_
-         { I => $I, mem_addr => $addr, op => OP_LOADA, CS => 0 }
+         { I => $I, mem_addr => $addr, op => OP_LOADA }
   }
 
 sub loadb {
@@ -103,7 +113,7 @@ sub loadb {
        $I |= $inv << 4;
        $I |= $alus << 5;
        send_
-         { I => $I, mem_addr => $addr, op => OP_LOADB, CS => 0 }
+         { I => $I, mem_addr => $addr, op => OP_LOADB }
   }
 
 #sub read_ {
@@ -118,26 +128,28 @@ sub store {
        $I |= $edge_ << 7;
        $I |= $cube << 8;
        send_
-         { I => $I, mem_addr => $addr, op => OP_STORE, CS => 0 }
+         { I => $I, mem_addr => $addr, op => OP_STORE }
   }
 
 sub loadi {
        my ($addr, $I) = @_;
        send_
-         { I => $I, mem_addr => $addr, op => OP_LOADI, CS => 0 }
+         { I => $I, mem_addr => $addr, op => OP_LOADI }
 }
 
 sub route {
-       my ($addr, $dest_addr) = @_;
+       my ($addr, $dest_addr, $led) = @_;
+       $led //= 0;
        my $I = $dest_addr;
+       $I |= $led << 12;
        send_
-         { I => $I, mem_addr => $addr, op => OP_ROUTE, CS => 0 }
+         { I => $I, mem_addr => $addr, op => OP_ROUTE }
 }
 
 sub storei {
        my ($addr, $I) = @_;
        send_
-         { I => $I, mem_addr => $addr, op => OP_STOREI, CS => 0 }
+         { I => $I, mem_addr => $addr, op => OP_STOREI }
 }
 
 sub led {
@@ -145,11 +157,12 @@ sub led {
        my $I = $offset_leds;
        $I |= $mode << 4;
        send_
-         { I => $I, mem_addr => $addr, op => OP_LED, CS => 0 }
+         { I => $I, mem_addr => $addr, op => OP_LED }
 }
 
 sub ledm {
        my ($addr, $offset) = @_;
+       $offset //= 0;
        led $addr, 1, $offset;
 }
 
@@ -207,6 +220,13 @@ sub alus_addAF { alu_of_function { ($a + $_) & 1 } }
 
 sub alu_or { alu_of_function { $a | $b | $_ } }
 
+sub alu_and { alu_of_function { $a & $b & $_ } }
+
+BEGIN {
+       die "alus_add != alu_xor" unless alus_add == alu_xor;
+       die "bad alu_select_f" unless alu_select_f == alu_of_function { $_ };
+}
+
 sub alu2 {
        my ($aluc, $alus, $addrA, $addrB, $flagr, $flagw, $cond, $inv) = @_;
        loada $addrA, $flagr, 0, $aluc;
@@ -221,6 +241,11 @@ sub alu3 {
        store $addrC, $flagw, 0, 0;
 }
 
+sub mov {
+       my ($addrA, $addrC) = @_;
+       alu3 alu_zero, alu_select_a, $addrA, $addrA, $addrC, flag_zero, flag_zero
+}
+
 sub add {
        my ($addrA, $addrB, $addrC, $flag_carry) = @_;
        alu3 aluc_add, alus_add, $addrA, $addrB, $addrC, flag_zero, $flag_carry;
@@ -231,6 +256,16 @@ sub addC {
        alu3 aluc_add, alus_add, $addrA, $addrB, $addrC, $flag_carry, $flag_carry;
 }
 
+sub xor_ {
+       my ($addrA, $addrB, $addrC) = @_;
+       alu3 alu_zero, alu_xor, $addrA, $addrB, $addrC, flag_zero, flag_zero;
+}
+
+sub and_ {
+       my ($addrA, $addrB, $addrC) = @_;
+       alu3 alu_zero, alu_and, $addrA, $addrB, $addrC, flag_zero, flag_zero;
+}
+
 # news_gen face partea de mijloc
 # news_[mf][mf] face primul alu3, apeleaza news_gen, apoi face ultimul alu3
 sub news_generic {
@@ -238,16 +273,18 @@ sub news_generic {
        my %dest = %$dest;
        while ($nX || $nY) {
                my $direction;
-               if ($nX && $nY) {
-                       $nX--;
-                       $nY--;
-                       $direction = 7;
-               } elsif ($nX) {
+               if ($nX > 0) {
                        $nX--;
+                       $direction = 2;
+               } elsif ($nX < 0) {
+                       $nX++;
                        $direction = 0;
-               } else {
+               } elsif ($nY > 0) {
                        $nY--;
-                       $direction = 6;
+                       $direction = 1;
+               } elsif ($nY < 0) {
+                       $nY++;
+                       $direction = 3;
                }
                if ($nX || $nY) { # not the last go
                        alu3 alu_select_f, alu_select_a, 0, 0, 0, flag_news($direction), flag_zero
This page took 0.013582 seconds and 4 git commands to generate.