]> iEval git - clump.git/blobdiff - asm.pm
Add diagrams and pictures
[clump.git] / asm.pm
diff --git a/asm.pm b/asm.pm
index d07004e5cc6cf65e78b1c42c7dfc617826b170bb..1b6dc8ad82e0d98ad48dd0583098eb8279979a7b 100644 (file)
--- a/asm.pm
+++ b/asm.pm
@@ -7,10 +7,10 @@ use constant +{
        OP_LOADA => 1,
        OP_LOADB => 2,
        OP_STORE => 3,
-       OP_READ => 4,
+       OP_STOREI => 4,
        OP_LOADI => 5,
        OP_ROUTE => 6,
-       OP_RUG => 7,
+       OP_LED => 7,
 };
 
 q,
@@ -28,19 +28,22 @@ $port->read_const_time(2000);
 $port->write_settings or die "$!";
 ,;
 
-use Fcntl;
+#use Fcntl;
 use Time::HiRes qw/sleep/;
 
-sysopen my $port, '/dev/ttyUSB1', O_SYNC | O_RDWR or die "$!";
+my $port;
+#sysopen $port, '/dev/ttyUSB1', O_SYNC | O_RDWR or die "$!";
 
 
 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/;
-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/;
+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';
 
-sub send_ {
+=begin comment
+
+sub send__ {
        my ($cmd) = @_;
        my %cmd = %$cmd;
 
@@ -60,6 +63,39 @@ sub send_ {
        }
 }
 
+=end
+
+
+=cut
+
+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{I}, $cmd{mem_addr}, $op_cs;
+       my $hex = reverse unpack 'h*', $binary;
+       #       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 }
+  }
+
 sub loada {
        my ($addr, $flagr, $bsel, $aluc) = @_;
        my $I = 0;
@@ -67,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 {
@@ -77,13 +113,13 @@ 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_ {
-       my ($addr) = @_;
-       send_ { I => 0, mem_addr => $addr, op => OP_READ, CS => 1 }
-}
+#sub read_ {
+#      my ($addr) = @_;
+#      send_ { I => 0, mem_addr => $addr, op => OP_READ, CS => 1 }
+#}
 
 sub store {
        my ($addr, $flagw, $edge_, $cube) = @_;
@@ -92,16 +128,51 @@ 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, $led) = @_;
+       $led //= 0;
+       my $I = $dest_addr;
+       $I |= $led << 12;
+       send_
+         { I => $I, mem_addr => $addr, op => OP_ROUTE }
+}
+
+sub storei {
+       my ($addr, $I) = @_;
+       send_
+         { I => $I, mem_addr => $addr, op => OP_STOREI }
+}
+
+sub led {
+       my ($addr, $mode, $offset_leds) = @_;
+       my $I = $offset_leds;
+       $I |= $mode << 4;
+       send_
+         { I => $I, mem_addr => $addr, op => OP_LED }
+}
+
+sub ledm {
+       my ($addr, $offset) = @_;
+       $offset //= 0;
+       led $addr, 1, $offset;
+}
+
+sub ledi {
+       my ($leds) = @_;
+       led 0, 0, $leds;
 }
 
 sub flag_zero { 0 }
+sub flag_temp { 7 }
 
 sub flag_news { 8 + $_[0] }
 
@@ -149,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;
@@ -163,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;
@@ -172,3 +255,71 @@ sub addC {
        my ($addrA, $addrB, $addrC, $flag_carry) = @_;
        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 {
+       my ($nX, $nY, $dest) = @_;
+       my %dest = %$dest;
+       while ($nX || $nY) {
+               my $direction;
+               if ($nX > 0) {
+                       $nX--;
+                       $direction = 2;
+               } elsif ($nX < 0) {
+                       $nX++;
+                       $direction = 0;
+               } elsif ($nY > 0) {
+                       $nY--;
+                       $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
+               } elsif (exists $dest{address}) {
+                       alu3 alu_select_f, alu_select_f, 0, 0, $dest{address}, flag_news($direction), flag_zero
+               } elsif (exists $dest{flag}) {
+                       alu3 alu_select_f, alu_select_a, 0, 0, 0, flag_news($direction), $dest{flag}
+               } else {
+                       die "No destination address nor flag given to [news_generic]\n"
+               }
+       }
+}
+
+sub news_mm {
+       my ($addrIN, $addrOUT, $nX, $nY) = @_;
+       alu3 alu_select_a, alu_select_a, $addrIN, 0, $addrIN, flag_zero, flag_zero;
+       news_generic $nX, $nY, {address => $addrOUT};
+}
+
+sub news_mf {
+       my ($addrIN, $flagOUT, $nX, $nY) = @_;
+       alu3 alu_select_a, alu_select_a, $addrIN, 0, $addrIN, flag_zero, flag_zero;
+       news_generic $nX, $nY, {flag => $flagOUT};
+}
+
+sub news_fm {
+       my ($flagIN, $addrOUT, $nX, $nY) = @_;
+       alu3 alu_select_f, alu_select_a, 0, 0, 0, $flagIN, flag_zero;
+       news_generic $nX, $nY, {address => $addrOUT};
+}
+
+sub news_ff {
+       my ($flagIN, $flagOUT, $nX, $nY) = @_;
+       alu3 alu_select_f, alu_select_a, 0, 0, 0, $flagIN, flag_zero;
+       news_generic $nX, $nY, {flag => $flagOUT};
+}
+
+1;
This page took 0.030162 seconds and 4 git commands to generate.